Mercurial > libervia-backend
annotate frontends/src/jp/base.py @ 1604:9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 15 Nov 2015 23:16:54 +0100 |
parents | 8d41cd4da2f6 |
children | 0aded9648c5c |
rev | line source |
---|---|
0 | 1 #! /usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
4 # jp: a SAT command line tool |
1396 | 5 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Jérôme Poisson (goffi@goffi.org) |
0 | 6 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
7 # This program is free software: you can redistribute it and/or modify |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
8 # it under the terms of the GNU Affero General Public License as published by |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
9 # the Free Software Foundation, either version 3 of the License, or |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
10 # (at your option) any later version. |
0 | 11 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
12 # This program is distributed in the hope that it will be useful, |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
15 # GNU Affero General Public License for more details. |
0 | 16 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
17 # You should have received a copy of the GNU Affero General Public License |
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
0 | 19 |
771 | 20 from sat.core.i18n import _ |
402
f03688bdb858
jp: use with statement to open fifo
Goffi <goffi@goffi.org>
parents:
401
diff
changeset
|
21 |
0 | 22 global pbar_available |
23 pbar_available = True #checked before using ProgressBar | |
24 | |
25 ### logging ### | |
26 import logging | |
27 from logging import debug, info, error, warning | |
28 logging.basicConfig(level=logging.DEBUG, | |
29 format='%(message)s') | |
30 ### | |
31 | |
32 import sys | |
817 | 33 import locale |
34 import os.path | |
35 import argparse | |
964 | 36 from gi.repository import GLib, GObject |
817 | 37 from glob import iglob |
38 from importlib import import_module | |
1139
75025461141f
move sat.tools.jid to sat_frontends.tools.jid
souliane <souliane@mailoo.org>
parents:
1033
diff
changeset
|
39 from sat_frontends.tools.jid import JID |
627
d207c2186519
core, bridge, jp, quick_frontend: SàT stop more gracefully if bridge can't be initialised:
Goffi <goffi@goffi.org>
parents:
613
diff
changeset
|
40 from sat_frontends.bridge.DBus import DBusBridgeFrontend |
817 | 41 from sat.core import exceptions |
42 import sat_frontends.jp | |
970
2e052998c7eb
jp: using C.APP_URL for application url
Goffi <goffi@goffi.org>
parents:
965
diff
changeset
|
43 from sat_frontends.jp.constants import Const as C |
0 | 44 try: |
817 | 45 import progressbar |
46 except ImportError: | |
47 info (_('ProgressBar not available, please download it at http://pypi.python.org/pypi/progressbar')) | |
48 info (_('Progress bar deactivated\n--\n')) | |
49 progressbar=None | |
50 | |
51 #consts | |
52 prog_name = u"jp" | |
53 description = """This software is a command line tool for XMPP. | |
970
2e052998c7eb
jp: using C.APP_URL for application url
Goffi <goffi@goffi.org>
parents:
965
diff
changeset
|
54 Get the latest version at """ + C.APP_URL |
817 | 55 |
1396 | 56 copyleft = u"""Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Jérôme Poisson (aka Goffi) |
817 | 57 This program comes with ABSOLUTELY NO WARRANTY; |
58 This is free software, and you are welcome to redistribute it under certain conditions. | |
59 """ | |
0 | 60 |
61 | |
817 | 62 def unicode_decoder(arg): |
63 # Needed to have unicode strings from arguments | |
64 return arg.decode(locale.getpreferredencoding()) | |
814 | 65 |
0 | 66 |
817 | 67 class Jp(object): |
814 | 68 """ |
69 This class can be use to establish a connection with the | |
70 bridge. Moreover, it should manage a main loop. | |
71 | |
72 To use it, you mainly have to redefine the method run to perform | |
73 specify what kind of operation you want to perform. | |
74 | |
75 """ | |
817 | 76 def __init__(self): |
165
8a2053de6f8c
Frontends: management of unlaunched SàT Backend (information message and exit)
Goffi <goffi@goffi.org>
parents:
156
diff
changeset
|
77 try: |
817 | 78 self.bridge = DBusBridgeFrontend() |
79 except exceptions.BridgeExceptionNoService: | |
165
8a2053de6f8c
Frontends: management of unlaunched SàT Backend (information message and exit)
Goffi <goffi@goffi.org>
parents:
156
diff
changeset
|
80 print(_(u"Can't connect to SàT backend, are you sure it's launched ?")) |
627
d207c2186519
core, bridge, jp, quick_frontend: SàT stop more gracefully if bridge can't be initialised:
Goffi <goffi@goffi.org>
parents:
613
diff
changeset
|
81 sys.exit(1) |
864
241f6baa6687
frontends: fix typos, do not use logging in the xmlui tools:
souliane <souliane@mailoo.org>
parents:
823
diff
changeset
|
82 except exceptions.BridgeInitError: |
627
d207c2186519
core, bridge, jp, quick_frontend: SàT stop more gracefully if bridge can't be initialised:
Goffi <goffi@goffi.org>
parents:
613
diff
changeset
|
83 print(_(u"Can't init bridge")) |
165
8a2053de6f8c
Frontends: management of unlaunched SàT Backend (information message and exit)
Goffi <goffi@goffi.org>
parents:
156
diff
changeset
|
84 sys.exit(1) |
814 | 85 |
817 | 86 self.parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, |
87 description=description) | |
88 | |
89 self._make_parents() | |
90 self.add_parser_options() | |
91 self.subparsers = self.parser.add_subparsers(title=_('Available commands'), dest='subparser_name') | |
92 self._auto_loop = False # when loop is used for internal reasons | |
93 self.need_loop = False # to set by commands when loop is needed | |
94 self._progress_id = None # TODO: manage several progress ids | |
95 self.quit_on_progress_end = True # set to False if you manage yourself exiting, or if you want the user to stop by himself | |
96 | |
97 @property | |
98 def version(self): | |
99 return self.bridge.getVersion() | |
814 | 100 |
817 | 101 @property |
102 def progress_id(self): | |
103 return self._progress_id | |
104 | |
105 @progress_id.setter | |
106 def progress_id(self, value): | |
107 self._progress_id = value | |
108 | |
1604
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
109 |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
110 def addOnQuitCallback(self, callback, *args, **kwargs): |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
111 """Add a callback which will be called on quit command |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
112 |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
113 @param callback(callback): method to call |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
114 """ |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
115 try: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
116 callbacks_list = self._onQuitCallbacks |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
117 except AttributeError: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
118 callbacks_list = self._onQuitCallbacks = [] |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
119 finally: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
120 callbacks_list.append((callback, args, kwargs)) |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
121 |
817 | 122 def _make_parents(self): |
123 self.parents = {} | |
124 | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
125 # we have a special case here as the start-session option is present only if connection is not needed, |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
126 # so we create two similar parents, one with the option, the other one without it |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
127 for parent_name in ('profile', 'profile_session'): |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
128 parent = self.parents[parent_name] = argparse.ArgumentParser(add_help=False) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
129 parent.add_argument("-p", "--profile", action="store", type=str, default='@DEFAULT@', help=_("Use PROFILE profile key (default: %(default)s)")) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
130 parent.add_argument("--pwd", action="store", type=unicode, default='', metavar='PASSWORD', help=_("Password used to connect profile, if necessary")) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
131 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
132 profile_parent, profile_session_parent = self.parents['profile'], self.parents['profile_session'] |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
133 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
134 connect_short, connect_long, connect_action, connect_help = "-c", "--connect", "store_true", _(u"Connect the profile before doing anything else") |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
135 profile_parent.add_argument(connect_short, connect_long, action=connect_action, help=connect_help) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
136 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
137 profile_session_connect_group = profile_session_parent.add_mutually_exclusive_group() |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
138 profile_session_connect_group.add_argument(connect_short, connect_long, action=connect_action, help=connect_help) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
139 profile_session_connect_group.add_argument("--start-session", action="store_true", help=_("Start a profile session without connecting")) |
817 | 140 |
141 progress_parent = self.parents['progress'] = argparse.ArgumentParser(add_help=False) | |
142 if progressbar: | |
823
300b4de701a6
jp: short option for progress is now -P instead of -g, so -g can be used for groups
Goffi <goffi@goffi.org>
parents:
817
diff
changeset
|
143 progress_parent.add_argument("-P", "--progress", action="store_true", help=_("Show progress bar")) |
0 | 144 |
1600 | 145 verbose_parent = self.parents['verbose'] = argparse.ArgumentParser(add_help=False) |
146 verbose_parent.add_argument('--verbose', '-v', action='count', help=_(u"Add a verbosity level (can be used multiple times)")) | |
147 | |
817 | 148 def add_parser_options(self): |
149 self.parser.add_argument('--version', action='version', version=("%(name)s %(version)s %(copyleft)s" % {'name': prog_name, 'version': self.version, 'copyleft': copyleft})) | |
150 | |
151 def import_commands(self): | |
152 """ Automaticaly import commands to jp | |
153 looks from modules names cmd_*.py in jp path and import them | |
154 | |
155 """ | |
156 path = os.path.dirname(sat_frontends.jp.__file__) | |
157 modules = (os.path.splitext(module)[0] for module in map(os.path.basename, iglob(os.path.join(path, "cmd_*.py")))) | |
158 for module_name in modules: | |
159 module = import_module("sat_frontends.jp."+module_name) | |
160 try: | |
161 self.import_command_module(module) | |
162 except ImportError: | |
163 continue | |
0 | 164 |
817 | 165 def import_command_module(self, module): |
166 """ Add commands from a module to jp | |
167 @param module: module containing commands | |
168 | |
169 """ | |
170 try: | |
171 for classname in module.__commands__: | |
172 cls = getattr(module, classname) | |
173 except AttributeError: | |
174 warning(_("Invalid module %s") % module) | |
175 raise ImportError | |
176 cls(self) | |
177 | |
178 | |
179 def run(self, args=None): | |
180 self.args = self.parser.parse_args(args) | |
181 self.args.func() | |
182 if self.need_loop or self._auto_loop: | |
183 self._start_loop() | |
184 | |
185 def _start_loop(self): | |
898
9720d3d0a764
jp: updated main loop to gobject 3
Matteo Cypriani <mcy@lm7.fr>
parents:
864
diff
changeset
|
186 self.loop = GLib.MainLoop() |
814 | 187 try: |
188 self.loop.run() | |
189 except KeyboardInterrupt: | |
190 info(_("User interruption: good bye")) | |
0 | 191 |
817 | 192 def stop_loop(self): |
193 try: | |
194 self.loop.quit() | |
195 except AttributeError: | |
196 pass | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
197 |
1604
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
198 def quitFromSignal(self, errcode=0): |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
199 """Same as self.quit, but from a signal handler |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
200 |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
201 /!\: return must be used after calling this method ! |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
202 """ |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
203 assert self.need_loop |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
204 # XXX: python-dbus will show a traceback if we exit in a signal handler with an error code |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
205 # so we use this little timeout trick to avoid it |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
206 GLib.timeout_add(0, self.quit, errcode) |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
207 |
817 | 208 def quit(self, errcode=0): |
1604
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
209 # first the onQuitCallbacks |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
210 try: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
211 callbacks_list = self._onQuitCallbacks |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
212 except AttributeError: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
213 pass |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
214 else: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
215 for callback, args, kwargs in callbacks_list: |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
216 callback(*args, **kwargs) |
9ac78437000d
jp (base): added quitFromSignal method to quit from signal handler with errcode without traceback, and addOnQuitCallback to manage cleaning callbacks
Goffi <goffi@goffi.org>
parents:
1600
diff
changeset
|
217 |
817 | 218 self.stop_loop() |
219 if errcode: | |
220 sys.exit(errcode) | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
221 |
814 | 222 def check_jids(self, jids): |
223 """Check jids validity, transform roster name to corresponding jids | |
110
cb904fa7de3c
jp: profile management (new option: --profile)
Goffi <goffi@goffi.org>
parents:
70
diff
changeset
|
224 |
817 | 225 @param profile: profile name |
226 @param jids: list of jids | |
227 @return: List of jids | |
228 | |
814 | 229 """ |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
230 names2jid = {} |
493
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
231 nodes2jid = {} |
393 | 232 |
814 | 233 for contact in self.bridge.getContacts(self.profile): |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
234 jid_s, attr, groups = contact |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
235 _jid = JID(jid_s) |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
236 try: |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
237 names2jid[attr["name"].lower()] = jid_s |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
238 except KeyError: |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
239 pass |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
240 |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
241 if _jid.node: |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
242 nodes2jid[_jid.node.lower()] = jid_s |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
243 |
817 | 244 def expand_jid(jid): |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
245 _jid = jid.lower() |
493
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
246 if _jid in names2jid: |
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
247 expanded = names2jid[_jid] |
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
248 elif _jid in nodes2jid: |
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
249 expanded = nodes2jid[_jid] |
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
250 else: |
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
251 expanded = jid |
965 | 252 return expanded.decode('utf-8') |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
253 |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
254 def check(jid): |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
255 if not jid.is_valid: |
814 | 256 error (_("%s is not a valid JID !"), jid) |
817 | 257 self.quit(1) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
258 |
814 | 259 dest_jids=[] |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
260 try: |
814 | 261 for i in range(len(jids)): |
817 | 262 dest_jids.append(expand_jid(jids[i])) |
814 | 263 check(dest_jids[i]) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
264 except AttributeError: |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
265 pass |
0 | 266 |
814 | 267 return dest_jids |
0 | 268 |
817 | 269 def connect_profile(self, callback): |
1588
823a385235ef
jp: fixed bad --connect option check
Goffi <goffi@goffi.org>
parents:
1544
diff
changeset
|
270 """ Check if the profile is connected and do it if requested |
1401
265ff2bd8d67
jp: fixed crash on commands using profile without "connect" option
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
271 |
817 | 272 @param callback: method to call when profile is connected |
273 @exit: - 1 when profile is not connected and --connect is not set | |
274 - 1 when the profile doesn't exists | |
275 - 1 when there is a connection error | |
276 """ | |
277 # FIXME: need better exit codes | |
278 | |
971
8ca5c990ed92
jp: "disco" subcommand, moved into a new "info" subcommand + added "version" subcommand which get software version
Goffi <goffi@goffi.org>
parents:
970
diff
changeset
|
279 def cant_connect(failure): |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
280 error(_(u"Can't connect profile: {reason}").format(reason=failure)) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
281 self.quit(1) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
282 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
283 def cant_start_session(failure): |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
284 error(_(u"Can't start {profile}'s session: {reason}").format(profile=self.profile, reason=failure)) |
817 | 285 self.quit(1) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
286 |
817 | 287 self.profile = self.bridge.getProfileName(self.args.profile) |
0 | 288 |
817 | 289 if not self.profile: |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
290 error(_("The profile [{profile}] doesn't exist").format(profile=self.args.profile)) |
817 | 291 self.quit(1) |
292 | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
293 try: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
294 start_session = self.args.start_session |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
295 except AttributeError: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
296 pass |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
297 else: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
298 if start_session: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
299 self.bridge.profileStartSession(self.args.pwd, self.profile, lambda dummy: callback(), cant_start_session) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
300 self._auto_loop = True |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
301 return |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
302 elif not self.bridge.profileIsSessionStarted(self.profile): |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
303 if not self.args.connect: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
304 error(_(u"Session for [{profile}] is not started, please start it before using jp, or use either --start-session or --connect option").format(profile=self.profile)) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
305 self.quit(1) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
306 else: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
307 callback() |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
308 return |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
309 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
310 |
1401
265ff2bd8d67
jp: fixed crash on commands using profile without "connect" option
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
311 if not hasattr(self.args, 'connect'): |
1588
823a385235ef
jp: fixed bad --connect option check
Goffi <goffi@goffi.org>
parents:
1544
diff
changeset
|
312 # a profile can be present without connect option (e.g. on profile creation/deletion) |
1401
265ff2bd8d67
jp: fixed crash on commands using profile without "connect" option
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
313 return |
1588
823a385235ef
jp: fixed bad --connect option check
Goffi <goffi@goffi.org>
parents:
1544
diff
changeset
|
314 elif self.args.connect is True: # if connection is asked, we connect the profile |
1544
3d5193b4c582
jp: separate password and connection of profile in --connect and --pwd arguments
Goffi <goffi@goffi.org>
parents:
1401
diff
changeset
|
315 self.bridge.asyncConnect(self.profile, self.args.pwd, lambda dummy: callback(), cant_connect) |
817 | 316 self._auto_loop = True |
814 | 317 return |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
318 else: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
319 if not self.bridge.isConnected(self.profile): |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
320 error(_(u"Profile [{profile}] is not connected, please connect it before using jp, or use --connect option").format(profile=self.profile)) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
321 self.quit(1) |
0 | 322 |
817 | 323 callback() |
324 | |
325 def get_full_jid(self, param_jid): | |
1290
faa1129559b8
core, frontends: refactoring to base Libervia on QuickFrontend (big mixed commit):
Goffi <goffi@goffi.org>
parents:
1139
diff
changeset
|
326 """Return the full jid if possible (add main resource when find a bare jid)""" |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
327 _jid = JID(param_jid) |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
328 if not _jid.resource: |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
329 #if the resource is not given, we try to add the last known resource |
1290
faa1129559b8
core, frontends: refactoring to base Libervia on QuickFrontend (big mixed commit):
Goffi <goffi@goffi.org>
parents:
1139
diff
changeset
|
330 last_resource = self.bridge.getMainResource(param_jid, self.profile) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
331 if last_resource: |
688
f7878ad3c846
tools: renamed tools.jid.JID attribute "short" to "bare"
souliane <souliane@mailoo.org>
parents:
657
diff
changeset
|
332 return "%s/%s" % (_jid.bare, last_resource) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
333 return param_jid |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
334 |
817 | 335 def watch_progress(self): |
336 self.pbar = None | |
898
9720d3d0a764
jp: updated main loop to gobject 3
Matteo Cypriani <mcy@lm7.fr>
parents:
864
diff
changeset
|
337 GObject.timeout_add(10, self._progress_cb) |
0 | 338 |
817 | 339 def _progress_cb(self): |
340 if self.progress_id: | |
341 data = self.bridge.getProgress(self.progress_id, self.profile) | |
342 if data: | |
343 if not data['position']: | |
344 data['position'] = '0' | |
345 if not self.pbar: | |
346 #first answer, we must construct the bar | |
347 self.pbar = progressbar.ProgressBar(int(data['size']), | |
348 [_("Progress: "),progressbar.Percentage(), | |
349 " ", | |
350 progressbar.Bar(), | |
351 " ", | |
352 progressbar.FileTransferSpeed(), | |
353 " ", | |
354 progressbar.ETA()]) | |
355 self.pbar.start() | |
356 | |
357 self.pbar.update(int(data['position'])) | |
358 | |
359 elif self.pbar: | |
360 self.pbar.finish() | |
361 if self.quit_on_progress_end: | |
362 self.quit() | |
363 return False | |
364 | |
365 return True | |
814 | 366 |
367 | |
817 | 368 class CommandBase(object): |
814 | 369 |
1600 | 370 def __init__(self, host, name, use_profile=True, use_progress=False, use_verbose=False, need_connect=None, help=None, **kwargs): |
817 | 371 """ Initialise CommandBase |
372 @param host: Jp instance | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
373 @param name(unicode): name of the new command |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
374 @param use_profile(bool): if True, add profile selection/connection commands |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
375 @param use_progress(bool): if True, add progress bar activation commands |
1600 | 376 @param use_verbose(bool): if True, add verbosity command |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
377 @param need_connect(bool, None): True if profile connection is needed |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
378 False else (profile session must still be started) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
379 None to set auto value (i.e. True if use_profile is set) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
380 Can't be set if use_profile is False |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
381 @param help(unicode): help message to display |
817 | 382 @param **kwargs: args passed to ArgumentParser |
383 | |
814 | 384 """ |
817 | 385 try: # If we have subcommands, host is a CommandBase and we need to use host.host |
386 self.host = host.host | |
387 except AttributeError: | |
388 self.host = host | |
389 | |
390 parents = kwargs.setdefault('parents', set()) | |
391 if use_profile: | |
392 #self.host.parents['profile'] is an ArgumentParser with profile connection arguments | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
393 if need_connect is None: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
394 need_connect = True |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
395 parents.add(self.host.parents['profile' if need_connect else 'profile_session']) |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
396 else: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
397 assert need_connect is None |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
398 |
817 | 399 if use_progress: |
400 parents.add(self.host.parents['progress']) | |
401 | |
1600 | 402 if use_verbose: |
403 parents.add(self.host.parents['verbose']) | |
404 | |
817 | 405 self.parser = host.subparsers.add_parser(name, help=help, **kwargs) |
406 if hasattr(self, "subcommands"): | |
407 self.subparsers = self.parser.add_subparsers() | |
408 else: | |
409 self.parser.set_defaults(func=self.run) | |
410 self.add_parser_options() | |
411 | |
412 @property | |
413 def args(self): | |
414 return self.host.args | |
415 | |
416 @property | |
417 def need_loop(self): | |
418 return self.host.need_loop | |
419 | |
420 @need_loop.setter | |
421 def need_loop(self, value): | |
422 self.host.need_loop = value | |
423 | |
424 @property | |
425 def profile(self): | |
426 return self.host.profile | |
427 | |
428 @property | |
429 def progress_id(self): | |
430 return self.host.progress_id | |
814 | 431 |
817 | 432 @progress_id.setter |
433 def progress_id(self, value): | |
434 self.host.progress_id = value | |
435 | |
436 def add_parser_options(self): | |
437 try: | |
438 subcommands = self.subcommands | |
439 except AttributeError: | |
440 # We don't have subcommands, the class need to implements add_parser_options | |
441 raise NotImplementedError | |
442 | |
443 # now we add subcommands to ourself | |
444 for cls in subcommands: | |
445 cls(self) | |
814 | 446 |
817 | 447 def run(self): |
448 try: | |
449 if self.args.profile: | |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
450 connect_profile = self.host.connect_profile |
817 | 451 except AttributeError: |
452 # the command doesn't need to connect profile | |
453 pass | |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
454 else: |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
455 connect_profile(self.connected) |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
456 |
817 | 457 try: |
458 if self.args.progress: | |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
459 watch_progress = self.host.watch_progress |
817 | 460 except AttributeError: |
461 # the command doesn't use progress bar | |
462 pass | |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
463 else: |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
464 watch_progress() |
817 | 465 |
466 def connected(self): | |
467 if not self.need_loop: | |
468 self.host.stop_loop() | |
469 | |
470 | |
471 class CommandAnswering(CommandBase): | |
472 #FIXME: temp, will be refactored when progress_bar/confirmations will be refactored | |
473 | |
474 def _ask_confirmation(self, confirm_id, confirm_type, data, profile): | |
475 """ Callback used for file transfer, accept files depending on parameters""" | |
538
2c4016921403
core, frontends, bridgen plugins: fixed methods which were unproperly managing multi-profiles
Goffi <goffi@goffi.org>
parents:
493
diff
changeset
|
476 if profile != self.profile: |
2c4016921403
core, frontends, bridgen plugins: fixed methods which were unproperly managing multi-profiles
Goffi <goffi@goffi.org>
parents:
493
diff
changeset
|
477 debug("Ask confirmation ignored: not our profile") |
2c4016921403
core, frontends, bridgen plugins: fixed methods which were unproperly managing multi-profiles
Goffi <goffi@goffi.org>
parents:
493
diff
changeset
|
478 return |
817 | 479 if confirm_type == self.confirm_type: |
480 if self.dest_jids and not JID(data['from']).bare in [JID(_jid).bare for _jid in self.dest_jids()]: | |
0 | 481 return #file is not sent by a filtered jid |
482 else: | |
817 | 483 self.ask(data, confirm_id) |
0 | 484 |
814 | 485 def ask(self): |
486 """ | |
487 The return value is used to answer to the bridge. | |
817 | 488 @return: bool or dict |
814 | 489 """ |
490 raise NotImplementedError | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
491 |
817 | 492 def connected(self): |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
493 """Auto reply to confirmations requests""" |
817 | 494 self.need_loop = True |
495 super(CommandAnswering, self).connected() | |
496 # we watch confirmation signals | |
497 self.host.bridge.register("ask_confirmation", self._ask_confirmation) | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
498 |
542
3eeb6c865e4d
frontends: incoming files transfer management:
Goffi <goffi@goffi.org>
parents:
538
diff
changeset
|
499 #and we ask those we have missed |
817 | 500 for confirm_id, confirm_type, data in self.host.bridge.getWaitingConf(self.profile): |
501 self._ask_confirmation(confirm_id, confirm_type, data, self.profile) |