~ubuntu-branches/ubuntu/hardy/pida/hardy

« back to all changes in this revision

Viewing changes to pida/core/application.py

  • Committer: Bazaar Package Importer
  • Author(s): Jan Luebbe
  • Date: 2007-09-05 17:54:09 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070905175409-ty9f6qpuctyjv1sd
Tags: 0.5.1-2
* Depend on librsvg2-common, which is not pulled in by the other depends
  (closes: #394860)
* gvim is no alternative for python-gnome2 and python-gnome2-extras
  (closes: #436431)
* Pida now uses ~/.pida2, so it can no longer be confused by old
  configurations (closes: #421378)
* Culebra is no longer supported by upstream (closes: #349009)
* Update manpage (closes: #440375)
* Update watchfile (pida is now called PIDA)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- coding: utf-8 -*- 
2
2
 
3
 
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
4
 
#Copyright (c) 2005 Ali Afshar aafshar@gmail.com
 
3
# Copyright (c) 2007 The PIDA Project
5
4
 
6
5
#Permission is hereby granted, free of charge, to any person obtaining a copy
7
6
#of this software and associated documentation files (the "Software"), to deal
21
20
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
21
#SOFTWARE.
23
22
 
 
23
 
24
24
# system import(s)
25
25
import os
26
26
import sys
27
 
import optparse
 
27
import signal
28
28
import warnings
29
 
import signal
30
 
import atexit
31
 
 
32
 
def die_cli(message):
 
29
 
 
30
from pida.core.signalhandler import PosixSignalHandler
 
31
 
 
32
# locale
 
33
from pida.core.locale import Locale
 
34
locale = Locale('pida')
 
35
_ = locale.gettext
 
36
 
 
37
def die_cli(message, exception=None):
33
38
    """Die in a command line way."""
34
39
    print message
35
 
    print 'Exiting. (this is fatal)'
 
40
    if exception:
 
41
        print exception
 
42
    print _('Exiting. (this is fatal)')
36
43
    sys.exit(1)
37
44
 
38
45
 
40
47
try:
41
48
    import gtk
42
49
    from gtk import gdk
 
50
    gdk.threads_init()
43
51
    if gtk.pygtk_version < (2, 8):
44
 
        die_cli('PIDA requires PyGTK >= 2.8. It only found %s.%s'
45
 
                % gtk.pygtk_version[:2])
46
 
except ImportError:
47
 
    die_cli('PIDA requires Python GTK bindings. They were not found.')
 
52
        die_cli(_('PIDA requires PyGTK >= 2.8. It only found %(major)s.%(minor)s')
 
53
                % {'major':gtk.pygtk_version[:2][0], 'minor':gtk.pygtk_version[:2][1]})
 
54
except ImportError, e:
 
55
    die_cli(_('PIDA requires Python GTK bindings. They were not found.'), e)
 
56
 
48
57
 
49
58
try:
50
 
    from rat import hig
51
 
    def die_gui(message):
 
59
    from kiwi.ui.dialogs import error
 
60
    def die_gui(message, exception):
52
61
        """Die in a GUI way."""
53
 
        hig.error("Fatal error, cannot start PIDA", 
54
 
                  message,
55
 
                  title="PIDA")
 
62
        error(_('Fatal error, cannot start PIDA'), 
 
63
              long='%s\n%s' % (message, exception))
56
64
        die_cli(message)
57
 
except ImportError:
58
 
    die_gui = die_cli
 
65
 
 
66
except ImportError, e:
 
67
    die_cli(_('Kiwi needs to be installed to run PIDA'), e)
 
68
 
59
69
 
60
70
# Python 2.4
61
71
if sys.version_info < (2,4):
62
 
    die_gui('Python 2.4 is required to run PIDA. Only %s.%s was found.' %
63
 
            sys.version_info[:2])
64
 
 
65
 
 
66
 
# Setuptools is needed to run PIDA
67
 
try:
68
 
    import setuptools
69
 
    import pkg_resources
70
 
    pkg_resources.require('pida')
71
 
except ImportError:
72
 
    die_gui('PIDA requires <i>setuptools</i> module to be installed.')
 
72
    die_gui(_('Python 2.4 is required to run PIDA. Only %(major)s.%(minor)s was found.') %
 
73
        {'major':sys.version_info[:2][0], 'minor':sys.version_info[:2][1]})
73
74
 
74
75
 
75
76
# This can test if PIDA is installed
76
77
try:
77
 
    from pida.core import boss
78
 
    from pida.pidagtk import debugwindow
79
 
    from pida.model import model
80
 
except ImportError:
81
 
    die_gui('PIDA is not correctly install, the <i>pida</i> module was not found.')
82
 
 
83
 
 
84
 
 
85
 
# Start lock threads here because an exception may be raised
86
 
# and the dialog would be frozen
87
 
gdk.threads_init()
88
 
gdk.threads_enter()
89
 
atexit.register(gdk.threads_leave)
90
 
 
91
 
# Now we can use a gui exception hook
92
 
old_excepthook = sys.excepthook
93
 
sys.excepthook = debugwindow.show
94
 
 
95
 
 
96
 
def get_version():
97
 
    from pkg_resources import resource_string
 
78
    from pida.core.environment import Environment
 
79
    from pida.core.boss import Boss
 
80
    from pida import PIDA_VERSION
 
81
except ImportError, e:
 
82
    die_gui(_('The pida package could not be found.'), e)
 
83
 
 
84
 
 
85
def run_version(env):
 
86
    print _('PIDA, version %s') % PIDA_VERSION
 
87
    return 0
 
88
 
 
89
 
 
90
def run_pida(env):
 
91
    b = Boss(env)
 
92
    PosixSignalHandler(b)
98
93
    try:
99
 
        version_file = resource_string('pida', 'data/version')
100
 
    except:
101
 
        version_file = 'unversioned'
102
 
    return version_file
103
 
 
104
 
 
105
 
pida_version = get_version()
106
 
 
107
 
 
108
 
class environment(object):
109
 
    """Handle environment variable and command line arguments"""
110
 
    def __init__(self):
111
 
        self.__editorname = None
112
 
        self.__parseargs()
113
 
 
114
 
    def __parseargs(self):
115
 
        home_dir_option = None
116
 
        default_home = os.path.join(os.path.expanduser('~'), '.pida')
117
 
 
118
 
        if default_home == os.path.join('~', '.pida') \
119
 
           and sys.platform == "win32":
120
 
           
121
 
            # When on win32
122
 
            from win32com.shell import shell, shellcon
123
 
            default_home = shell.SHGetSpecialFolderLocation(
124
 
                0,
125
 
                shellcon.CSIDL_APPDATA
126
 
            )
127
 
            default_home = shell.SHGetPathFromIDList(default_home)
128
 
            default_home = os.path.join(default_home, "Pida")
129
 
            del shell
130
 
            del shellcon
131
 
            
132
 
        op = optparse.OptionParser()
133
 
        op.add_option('-d', '--home-directory', type='string', nargs=1,
134
 
            action='store',
135
 
            help=('The location of the pida home directory. '
136
 
                  'If this directory does not exist, it will be created. '
137
 
                  'Default: %s' % default_home),
138
 
            default=default_home)
139
 
        op.add_option('-o', '--option', type='string', nargs=1,
140
 
            action='append',
141
 
            help=('Set an option. Options should be in the form: '
142
 
                  'servicename/group/name=value. '
143
 
                  'For example (without quotes): '
144
 
                  '"pida -o editormanager/general/editor_type=Vim". '
145
 
                  'More than one option can be set by repeated use of -o.'))
146
 
        op.add_option('-v', '--version', action='store_true',
147
 
                      help='Print version information and exit.')
148
 
        op.add_option('-D', '--debug', action='store_true',
149
 
            help=('Run PIDA with added debug information. '
150
 
                  'This merely sets the environment variables: '
151
 
                  'PIDA_DEBUG=1 and PIDA_LOG_STDERR=1, '
152
 
                  'and so the same effect may be achieved by setting them.'))
153
 
        op.add_option('-r', '--remote', action='store_true',
154
 
            help=('Run PIDA remotely to open a file in an existing instance '
155
 
                  'of PIDA. Usage pida -r <filename>.'))
156
 
        op.add_option('-F', '--first-run-wizard', action='store_true',
157
 
                      help='Run the PIDA first time wizard')
158
 
        op.add_option('-t', '--testing-mode', action='store_true',
159
 
                      help='Run te PIDA self test')
160
 
        opts, args = op.parse_args()
161
 
        envhome = self.__parseenv()
162
 
        if envhome is not None:
163
 
            home_dir_option = envhome
164
 
        else:
165
 
            home_dir_option = opts.home_directory
166
 
        self.__home_dir = home_dir_option
167
 
        self.__create_home_tree(self.__home_dir)
168
 
        self.__args = args
169
 
        self.opts = opts
170
 
 
171
 
    def __parseenv(self):
172
 
        if 'PIDA_HOME' in os.environ:
173
 
            return os.environ['PIDA_HOME']
174
 
 
175
 
    def __create_home_tree(self, root):
176
 
        dirs = {}
177
 
        self.__mkdir(root)
178
 
        for name in ['conf', 'log', 'run', 'vcs', 'sockets', 'data',
179
 
                     'projects', 'library']:
180
 
            path = os.path.join(root, name)
181
 
            self.__mkdir(path)
182
 
            dirs[name] = path
183
 
        return dirs
184
 
 
185
 
    def __mkdir(self, path):
186
 
        if not os.path.exists(path):
187
 
            os.mkdir(path)
188
 
 
189
 
    def get_positional_args(self):
190
 
        return self.__args
191
 
    positional_args = property(get_positional_args)
192
 
 
193
 
    def get_home_dir(self):
194
 
        return self.__home_dir
195
 
    home_dir = property(get_home_dir)
196
 
 
197
 
    def get_version(self):
198
 
        return pida_version
199
 
    version = property(get_version)
200
 
 
201
 
    def override_configuration_system(self, services):
202
 
        if self.__editorname:
203
 
            svc = services.get('editormanager')
204
 
            svc.opts.general__type = self.__editorname
205
 
        if not self.opts.option:
206
 
            return
207
 
        for opt in self.opts.option:
208
 
            if '=' in opt:
209
 
                name, value = opt.split('=', 1)
210
 
                if '/' in name:
211
 
                    parts = name.split('/', 3)
212
 
                    if len(parts) == 3:
213
 
                        service, group, option = parts
214
 
                        try:
215
 
                            svc = services.get(service)
216
 
                            optname = '%s__%s' % (group, option)
217
 
                            model.property_evading_setattr(svc.opts,
218
 
                                optname, value)
219
 
                        except:
220
 
                            print ('failed to set an option %s %s' %
221
 
                                    (service, group, option))
222
 
 
223
 
    def override_editor_option(self, editorname):
224
 
        self.__editorname = editorname
225
 
 
226
 
class PosixSignalHandler(object):
227
 
 
228
 
    def __init__(self, app):
229
 
        self._app = app
230
 
        signal.signal(signal.SIGTERM, self.handle_SIGTERM)
231
 
 
232
 
    def handle_SIGTERM(self, signum):
233
 
        self.log.error('PIDA stopped by SIGTERM') 
234
 
        self._app.boss.stop()
235
 
        
236
 
 
237
 
class application(object):
238
 
    """The PIDA Application."""
239
 
 
240
 
    def __init__(self,
241
 
                 bosstype=boss.boss,
242
 
                 mainloop=gtk.main,
243
 
                 mainstop=gtk.main_quit,
244
 
                 environment=environment()):
245
 
        self._signal_handler = PosixSignalHandler(self)
246
 
        self.__mainloop = mainloop
247
 
        self.__mainstop = mainstop
248
 
        self.__env = environment
249
 
        self.__boss = bosstype(application=self, env=self.__env)
250
 
        self.boss = self.__boss
251
 
        self.env = self.__env
252
 
 
253
 
    def start(self):
254
 
        """Start PIDA."""
255
 
        self.__boss.start()
256
 
        self.__mainloop()
257
 
 
258
 
    def stop(self):
259
 
        """Stop PIDA."""
260
 
        self.__mainstop()
261
 
 
262
 
 
263
 
def run_pida(env, bosstype, mainloop, mainstop):
264
 
    app = application(bosstype, mainloop, mainstop, env)
265
 
    if run_firstrun(env, app.boss):
266
 
        app.start()
 
94
        start_success = b.start()
 
95
    except Exception, e:
 
96
        print e
 
97
        start_success = False
 
98
    if start_success:
 
99
        gdk.threads_enter()
 
100
        b.loop_ui()
 
101
        gdk.threads_leave()
267
102
        return 0
268
103
    else:
269
104
        return 1
270
105
 
271
 
 
272
 
def run_version(env, *args):
273
 
    print 'PIDA, version %s' % pida_version
274
 
    return 0
275
 
 
276
 
 
277
 
def run_remote(env, *args):
278
 
    import pida.utils.pidaremote as pidaremote
279
 
    pidaremote.main(env.home_dir, env.positional_args)
280
 
    return 0
281
 
 
282
 
 
283
 
def run_firstrun(env, boss):
284
 
    first_filaname = os.path.join(env.home_dir, '.firstrun')
285
 
    
286
 
    if not os.path.exists(first_filaname) or env.opts.first_run_wizard:
287
 
        import pida.utils.firstrun as firstrun
288
 
        ftw = firstrun.FirstTimeWindow(boss.editors)
289
 
        response, editor = ftw.run(first_filaname)
290
 
        if response == gtk.RESPONSE_ACCEPT:
291
 
            if editor is None:
292
 
                raise RuntimeError('No Working Editors')
293
 
            else:
294
 
                env.override_editor_option(editor)
295
 
                return True
296
 
        else:
297
 
            return False
298
 
    else:
299
 
        return True
300
 
 
301
 
 
302
 
def main(bosstype=boss.boss, mainloop=gtk.main, mainstop=gtk.main_quit):
303
 
    warnings.filterwarnings("ignore", category=DeprecationWarning)
304
 
    env = environment()
305
 
    if env.opts.debug:
 
106
def force_quit(signum, frame):
 
107
    os.kill(os.getpid(), 9)
 
108
 
 
109
# Set the signal handler and a 5-second alarm
 
110
 
 
111
def set_trace():
 
112
    import linecache
 
113
    def traceit(frame, event, arg):
 
114
        ss = frame.f_code.co_stacksize
 
115
        fn = frame.f_code.co_filename
 
116
        ln = frame.f_lineno
 
117
        co = linecache.getline(fn, ln).strip()
 
118
        print '%s %s:%s %s' % (ss * '>', fn, ln, co)
 
119
        for k, i in frame.f_locals.items():
 
120
            try:
 
121
                print '%s=%s' % (k, i)
 
122
            except:
 
123
                print k, 'unable to print value'
 
124
        print
 
125
    sys.settrace(traceit)
 
126
 
 
127
def main():
 
128
    env = Environment(sys.argv)
 
129
    sys.argv = sys.argv[:1]
 
130
    if env.is_debug():
306
131
        os.environ['PIDA_DEBUG'] = '1'
307
132
        os.environ['PIDA_LOG_STDERR'] = '1'
308
 
    if env.opts.testing_mode:
309
 
        sys.excepthook = old_excepthook
310
 
    if env.opts.version is not None:
 
133
    else:
 
134
        warnings.filterwarnings("ignore")
 
135
    if env.is_trace():
 
136
        set_trace()
 
137
    if env.is_version():
311
138
        run_func = run_version
312
 
    elif env.opts.remote:
313
 
        run_func = run_remote
314
139
    else:
315
140
        run_func = run_pida
316
 
 
317
 
    exit_val = run_func(env, bosstype, mainloop, mainstop)
 
141
    exit_val = run_func(env)
 
142
    signal.signal(signal.SIGALRM, force_quit)
 
143
    signal.alarm(3)
318
144
    sys.exit(exit_val)
319
145
 
320
146
 
321
 
if __name__ == '__main__':
322
 
    main()
 
147
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: