Mercurial > libervia-backend
annotate sat_frontends/jp/base.py @ 3794:a58715ffa445
core (constants): type hints
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 17 Jun 2022 14:15:23 +0200 |
parents | ea204216a505 |
children | 3260401fdb98 |
rev | line source |
---|---|
3043
3df611adb598
jp: handle dbus bridge with asyncio:
Goffi <goffi@goffi.org>
parents:
3040
diff
changeset
|
1 #!/usr/bin/env python3 |
0 | 2 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
3 # jp: a SAT command line tool |
3479 | 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) |
0 | 5 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
6 # 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
|
7 # 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
|
8 # 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
|
9 # (at your option) any later version. |
0 | 10 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
11 # 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
|
12 # 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
|
13 # 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
|
14 # GNU Affero General Public License for more details. |
0 | 15 |
609
84a6e83157c2
fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents:
601
diff
changeset
|
16 # 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
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
0 | 18 |
3040 | 19 import asyncio |
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 ### logging ### |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
23 import logging as log |
3040 | 24 log.basicConfig(level=log.WARNING, |
25 format='[%(name)s] %(message)s') | |
0 | 26 ### |
27 | |
28 import sys | |
3040 | 29 import os |
817 | 30 import os.path |
31 import argparse | |
3040 | 32 import inspect |
3046 | 33 import tty |
34 import termios | |
3040 | 35 from pathlib import Path |
817 | 36 from glob import iglob |
3600
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
37 from typing import Optional |
817 | 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 |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
40 from sat.tools import config |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
41 from sat.tools.common import dynamic_import |
2532 | 42 from sat.tools.common import uri |
2704
ab37d1c7c38c
jp (base): new date_decoder to specify dates in arguments
Goffi <goffi@goffi.org>
parents:
2692
diff
changeset
|
43 from sat.tools.common import date_utils |
3046 | 44 from sat.tools.common import utils |
3586
5f65f4e9f8cb
plugin XEP-0060: getItems extra is now serialised dict
Goffi <goffi@goffi.org>
parents:
3568
diff
changeset
|
45 from sat.tools.common import data_format |
3046 | 46 from sat.tools.common.ansi import ANSI as A |
817 | 47 from sat.core import exceptions |
48 import sat_frontends.jp | |
3043
3df611adb598
jp: handle dbus bridge with asyncio:
Goffi <goffi@goffi.org>
parents:
3040
diff
changeset
|
49 from sat_frontends.jp.loops import QuitException, getJPLoop |
970
2e052998c7eb
jp: using C.APP_URL for application url
Goffi <goffi@goffi.org>
parents:
965
diff
changeset
|
50 from sat_frontends.jp.constants import Const as C |
3049
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
51 from sat_frontends.bridge.bridge_frontend import BridgeException |
2532 | 52 from sat_frontends.tools import misc |
1840
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
53 import xml.etree.ElementTree as ET # FIXME: used temporarily to manage XMLUI |
1950 | 54 from collections import OrderedDict |
1872
df1ca137b0cb
jp (blog/edit): editor arguments can now be specified on sat.conf, and default on are applied for known editors:
Goffi <goffi@goffi.org>
parents:
1869
diff
changeset
|
55 |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
56 ## bridge handling |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
57 # we get bridge name from conf and initialise the right class accordingly |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
58 main_config = config.parseMainConf() |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
59 bridge_name = config.getConfig(main_config, '', 'bridge', 'dbus') |
3043
3df611adb598
jp: handle dbus bridge with asyncio:
Goffi <goffi@goffi.org>
parents:
3040
diff
changeset
|
60 JPLoop = getJPLoop(bridge_name) |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
61 |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
62 |
0 | 63 try: |
817 | 64 import progressbar |
65 except ImportError: | |
3040 | 66 msg = (_('ProgressBar not available, please download it at ' |
67 'http://pypi.python.org/pypi/progressbar\n' | |
68 'Progress bar deactivated\n--\n')) | |
69 print(msg, file=sys.stderr) | |
817 | 70 progressbar=None |
71 | |
72 #consts | |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
73 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
|
74 Get the latest version at """ + C.APP_URL |
817 | 75 |
3479 | 76 COPYLEFT = """Copyright (C) 2009-2021 Jérôme Poisson, Adrien Cossa |
817 | 77 This program comes with ABSOLUTELY NO WARRANTY; |
78 This is free software, and you are welcome to redistribute it under certain conditions. | |
79 """ | |
0 | 80 |
3040 | 81 PROGRESS_DELAY = 0.1 # the progression will be checked every PROGRESS_DELAY s |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
82 |
0 | 83 |
2704
ab37d1c7c38c
jp (base): new date_decoder to specify dates in arguments
Goffi <goffi@goffi.org>
parents:
2692
diff
changeset
|
84 def date_decoder(arg): |
ab37d1c7c38c
jp (base): new date_decoder to specify dates in arguments
Goffi <goffi@goffi.org>
parents:
2692
diff
changeset
|
85 return date_utils.date_parse_ext(arg, default_tz=date_utils.TZ_LOCAL) |
ab37d1c7c38c
jp (base): new date_decoder to specify dates in arguments
Goffi <goffi@goffi.org>
parents:
2692
diff
changeset
|
86 |
ab37d1c7c38c
jp (base): new date_decoder to specify dates in arguments
Goffi <goffi@goffi.org>
parents:
2692
diff
changeset
|
87 |
3481
7892585b7e17
core (setup), jp, primitivus: update console scripts + classifiers:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
88 class LiberviaCli: |
814 | 89 """ |
90 This class can be use to establish a connection with the | |
91 bridge. Moreover, it should manage a main loop. | |
92 | |
93 To use it, you mainly have to redefine the method run to perform | |
94 specify what kind of operation you want to perform. | |
95 | |
96 """ | |
817 | 97 def __init__(self): |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
98 """ |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
99 |
3040 | 100 @attribute quit_on_progress_end (bool): set to False if you manage yourself |
101 exiting, or if you want the user to stop by himself | |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
102 @attribute progress_success(callable): method to call when progress just started |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
103 by default display a message |
3040 | 104 @attribute progress_success(callable): method to call when progress is |
105 successfully finished by default display a message | |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
106 @attribute progress_failure(callable): method to call when progress failed |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
107 by default display a message |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
108 """ |
3046 | 109 self.sat_conf = main_config |
110 self.set_color_theme() | |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
111 bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge') |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
112 if bridge_module is None: |
3028 | 113 log.error("Can't import {} bridge".format(bridge_name)) |
165
8a2053de6f8c
Frontends: management of unlaunched SàT Backend (information message and exit)
Goffi <goffi@goffi.org>
parents:
156
diff
changeset
|
114 sys.exit(1) |
814 | 115 |
3040 | 116 self.bridge = bridge_module.AIOBridge() |
117 self._onQuitCallbacks = [] | |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
118 |
3555
53fec6309fa3
cli: update constants to use new name
Goffi <goffi@goffi.org>
parents:
3547
diff
changeset
|
119 def get_config(self, name, section=C.CONFIG_SECTION, default=None): |
3046 | 120 """Retrieve a setting value from sat.conf""" |
121 return config.getConfig(self.sat_conf, section, name, default=default) | |
122 | |
123 def guess_background(self): | |
3704
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
124 # cf. https://unix.stackexchange.com/a/245568 (thanks!) |
3046 | 125 try: |
3704
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
126 # for VTE based terminals |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
127 vte_version = int(os.getenv("VTE_VERSION", 0)) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
128 except ValueError: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
129 vte_version = 0 |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
130 |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
131 color_fg_bg = os.getenv("COLORFGBG") |
3046 | 132 |
3704
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
133 if ((sys.stdin.isatty() and sys.stdout.isatty() |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
134 and ( |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
135 # XTerm |
3706
5131ed9163c0
cli (base): use `XTERM_VERSION` to detect XTerm:
Goffi <goffi@goffi.org>
parents:
3705
diff
changeset
|
136 os.getenv("XTERM_VERSION") |
3704
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
137 # Konsole |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
138 or os.getenv("KONSOLE_VERSION") |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
139 # All VTE based terminals |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
140 or vte_version >= 3502 |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
141 ))): |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
142 # ANSI escape sequence |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
143 stdin_fd = sys.stdin.fileno() |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
144 old_settings = termios.tcgetattr(stdin_fd) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
145 try: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
146 tty.setraw(sys.stdin.fileno()) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
147 # we request background color |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
148 sys.stdout.write("\033]11;?\a") |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
149 sys.stdout.flush() |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
150 expected = "\033]11;rgb:" |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
151 for c in expected: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
152 ch = sys.stdin.read(1) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
153 if ch != c: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
154 # background id is not supported, we default to "dark" |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
155 # TODO: log something? |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
156 return 'dark' |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
157 red, green, blue = [ |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
158 int(c, 16)/65535 for c in sys.stdin.read(14).split('/') |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
159 ] |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
160 # '\a' is the last character |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
161 sys.stdin.read(1) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
162 finally: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
163 termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
164 |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
165 lum = utils.per_luminance(red, green, blue) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
166 if lum <= 0.5: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
167 return 'dark' |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
168 else: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
169 return 'light' |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
170 elif color_fg_bg: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
171 # no luck with ANSI escape sequence, we try COLORFGBG environment variable |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
172 try: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
173 bg = int(color_fg_bg.split(";")[-1]) |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
174 except ValueError: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
175 return "dark" |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
176 if bg in list(range(7)) + [8]: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
177 return "dark" |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
178 else: |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
179 return "light" |
3046 | 180 else: |
3704
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
181 # no autodetection method found |
c143e7f35074
cli (base): better background detection:
Goffi <goffi@goffi.org>
parents:
3636
diff
changeset
|
182 return "dark" |
3046 | 183 |
184 def set_color_theme(self): | |
185 background = self.get_config('background', default='auto') | |
186 if background == 'auto': | |
187 background = self.guess_background() | |
188 if background not in ('dark', 'light'): | |
189 raise exceptions.ConfigError(_( | |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
190 'Invalid value set for "background" ({background}), please check ' |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
191 'your settings in libervia.conf').format( |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
192 background=repr(background) |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
193 )) |
3705
691dbd78981c
cli (debug/theme): display currently used background
Goffi <goffi@goffi.org>
parents:
3704
diff
changeset
|
194 self.background = background |
3046 | 195 if background == 'light': |
196 C.A_HEADER = A.FG_MAGENTA | |
197 C.A_SUBHEADER = A.BOLD + A.FG_RED | |
198 C.A_LEVEL_COLORS = (C.A_HEADER, A.BOLD + A.FG_BLUE, A.FG_MAGENTA, A.FG_CYAN) | |
199 C.A_SUCCESS = A.FG_GREEN | |
200 C.A_FAILURE = A.BOLD + A.FG_RED | |
201 C.A_WARNING = A.FG_RED | |
202 C.A_PROMPT_PATH = A.FG_BLUE | |
203 C.A_PROMPT_SUF = A.BOLD | |
204 C.A_DIRECTORY = A.BOLD + A.FG_MAGENTA | |
205 C.A_FILE = A.FG_BLACK | |
206 | |
3040 | 207 def _bridgeConnected(self): |
208 self.parser = argparse.ArgumentParser( | |
209 formatter_class=argparse.RawDescriptionHelpFormatter, description=DESCRIPTION) | |
817 | 210 self._make_parents() |
211 self.add_parser_options() | |
3040 | 212 self.subparsers = self.parser.add_subparsers( |
213 title=_('Available commands'), dest='command', required=True) | |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
214 |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
215 # progress attributes |
817 | 216 self._progress_id = None # TODO: manage several progress ids |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
217 self.quit_on_progress_end = True |
817 | 218 |
1950 | 219 # outputs |
220 self._outputs = {} | |
221 for type_ in C.OUTPUT_TYPES: | |
222 self._outputs[type_] = OrderedDict() | |
2189
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
223 self.default_output = {} |
1950 | 224 |
2705
0bb811aaf11d
jp (base): new own_jid host attribute:
Goffi <goffi@goffi.org>
parents:
2704
diff
changeset
|
225 self.own_jid = None # must be filled at runtime if needed |
0bb811aaf11d
jp (base): new own_jid host attribute:
Goffi <goffi@goffi.org>
parents:
2704
diff
changeset
|
226 |
817 | 227 @property |
228 def progress_id(self): | |
229 return self._progress_id | |
230 | |
3040 | 231 async def set_progress_id(self, progress_id): |
232 # because we use async, we need an explicit setter | |
233 self._progress_id = progress_id | |
234 await self.replayCache('progress_ids_cache') | |
817 | 235 |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
236 @property |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
237 def watch_progress(self): |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
238 try: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
239 self.pbar |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
240 except AttributeError: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
241 return False |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
242 else: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
243 return True |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
244 |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
245 @watch_progress.setter |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
246 def watch_progress(self, watch_progress): |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
247 if watch_progress: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
248 self.pbar = None |
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
|
249 |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
250 @property |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
251 def verbosity(self): |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
252 try: |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
253 return self.args.verbose |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
254 except AttributeError: |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
255 return 0 |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
256 |
3040 | 257 async def replayCache(self, cache_attribute): |
1642
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
258 """Replay cached signals |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
259 |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
260 @param cache_attribute(str): name of the attribute containing the cache |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
261 if the attribute doesn't exist, there is no cache and the call is ignored |
3040 | 262 else the cache must be a list of tuples containing the replay callback as |
263 first item, then the arguments to use | |
1642
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
264 """ |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
265 try: |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
266 cache = getattr(self, cache_attribute) |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
267 except AttributeError: |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
268 pass |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
269 else: |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
270 for cache_data in cache: |
3040 | 271 await cache_data[0](*cache_data[1:]) |
1642
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
272 |
3407
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
273 def disp(self, msg, verbosity=0, error=False, end='\n'): |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
274 """Print a message to user |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
275 |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
276 @param msg(unicode): message to print |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
277 @param verbosity(int): minimal verbosity to display the message |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
278 @param error(bool): if True, print to stderr instead of stdout |
3407
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
279 @param end(str): string appended after the last value, default a newline |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
280 """ |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
281 if self.verbosity >= verbosity: |
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
282 if error: |
3407
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
283 print(msg, end=end, file=sys.stderr) |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
284 else: |
3407
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
285 print(msg, end=end) |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
286 |
3040 | 287 async def output(self, type_, name, extra_outputs, data): |
2155 | 288 if name in extra_outputs: |
3040 | 289 method = extra_outputs[name] |
2155 | 290 else: |
3040 | 291 method = self._outputs[type_][name]['callback'] |
292 | |
293 ret = method(data) | |
294 if inspect.isawaitable(ret): | |
295 await ret | |
1950 | 296 |
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
|
297 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
|
298 """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
|
299 |
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
|
300 @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
|
301 """ |
3040 | 302 self._onQuitCallbacks.append((callback, args, kwargs)) |
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
|
303 |
1950 | 304 def getOutputChoices(self, output_type): |
305 """Return valid output filters for output_type | |
306 | |
307 @param output_type: True for default, | |
308 else can be any registered type | |
309 """ | |
3028 | 310 return list(self._outputs[output_type].keys()) |
1950 | 311 |
817 | 312 def _make_parents(self): |
313 self.parents = {} | |
314 | |
3040 | 315 # we have a special case here as the start-session option is present only if |
316 # connection is not needed, so we create two similar parents, one with the | |
317 # option, the other one without it | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
318 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
|
319 parent = self.parents[parent_name] = argparse.ArgumentParser(add_help=False) |
3040 | 320 parent.add_argument( |
321 "-p", "--profile", action="store", type=str, default='@DEFAULT@', | |
322 help=_("Use PROFILE profile key (default: %(default)s)")) | |
323 parent.add_argument( | |
3049
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
324 "--pwd", action="store", metavar='PASSWORD', |
3040 | 325 help=_("Password used to connect profile, if necessary")) |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
326 |
3040 | 327 profile_parent, profile_session_parent = (self.parents['profile'], |
328 self.parents['profile_session']) | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
329 |
3040 | 330 connect_short, connect_long, connect_action, connect_help = ( |
331 "-c", "--connect", "store_true", | |
332 _("Connect the profile before doing anything else") | |
333 ) | |
334 profile_parent.add_argument( | |
335 connect_short, connect_long, action=connect_action, help=connect_help) | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
336 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
337 profile_session_connect_group = profile_session_parent.add_mutually_exclusive_group() |
3040 | 338 profile_session_connect_group.add_argument( |
339 connect_short, connect_long, action=connect_action, help=connect_help) | |
340 profile_session_connect_group.add_argument( | |
341 "--start-session", action="store_true", | |
342 help=_("Start a profile session without connecting")) | |
817 | 343 |
3040 | 344 progress_parent = self.parents['progress'] = argparse.ArgumentParser( |
345 add_help=False) | |
817 | 346 if progressbar: |
3040 | 347 progress_parent.add_argument( |
348 "-P", "--progress", action="store_true", help=_("Show progress bar")) | |
0 | 349 |
1600 | 350 verbose_parent = self.parents['verbose'] = argparse.ArgumentParser(add_help=False) |
3040 | 351 verbose_parent.add_argument( |
352 '--verbose', '-v', action='count', default=0, | |
353 help=_("Add a verbosity level (can be used multiple times)")) | |
1600 | 354 |
3412
7b4ae3dbc041
jp (base, pubsub/set): new `--quiet` argument:
Goffi <goffi@goffi.org>
parents:
3409
diff
changeset
|
355 quiet_parent = self.parents['quiet'] = argparse.ArgumentParser(add_help=False) |
7b4ae3dbc041
jp (base, pubsub/set): new `--quiet` argument:
Goffi <goffi@goffi.org>
parents:
3409
diff
changeset
|
356 quiet_parent.add_argument( |
7b4ae3dbc041
jp (base, pubsub/set): new `--quiet` argument:
Goffi <goffi@goffi.org>
parents:
3409
diff
changeset
|
357 '--quiet', '-q', action='store_true', |
7b4ae3dbc041
jp (base, pubsub/set): new `--quiet` argument:
Goffi <goffi@goffi.org>
parents:
3409
diff
changeset
|
358 help=_("be quiet (only output machine readable data)")) |
7b4ae3dbc041
jp (base, pubsub/set): new `--quiet` argument:
Goffi <goffi@goffi.org>
parents:
3409
diff
changeset
|
359 |
2532 | 360 draft_parent = self.parents['draft'] = argparse.ArgumentParser(add_help=False) |
361 draft_group = draft_parent.add_argument_group(_('draft handling')) | |
3040 | 362 draft_group.add_argument( |
363 "-D", "--current", action="store_true", help=_("load current draft")) | |
364 draft_group.add_argument( | |
365 "-F", "--draft-path", type=Path, help=_("path to a draft file to retrieve")) | |
2532 | 366 |
367 | |
2547
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
368 def make_pubsub_group(self, flags, defaults): |
3600
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
369 """Generate pubsub options according to flags |
2532 | 370 |
371 @param flags(iterable[unicode]): see [CommandBase.__init__] | |
2547
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
372 @param defaults(dict[unicode, unicode]): help text for default value |
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
373 key can be "service" or "node" |
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
374 value will be set in " (DEFAULT: {value})", or can be None to remove DEFAULT |
2532 | 375 @return (ArgumentParser): parser to add |
376 """ | |
377 flags = misc.FlagsHandler(flags) | |
378 parent = argparse.ArgumentParser(add_help=False) | |
379 pubsub_group = parent.add_argument_group('pubsub') | |
3028 | 380 pubsub_group.add_argument("-u", "--pubsub-url", |
381 help=_("Pubsub URL (xmpp or http)")) | |
2532 | 382 |
3028 | 383 service_help = _("JID of the PubSub service") |
2532 | 384 if not flags.service: |
3028 | 385 default = defaults.pop('service', _('PEP service')) |
2547
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
386 if default is not None: |
3028 | 387 service_help += _(" (DEFAULT: {default})".format(default=default)) |
388 pubsub_group.add_argument("-s", "--service", default='', | |
2532 | 389 help=service_help) |
390 | |
3028 | 391 node_help = _("node to request") |
2532 | 392 if not flags.node: |
3028 | 393 default = defaults.pop('node', _('standard node')) |
2547
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
394 if default is not None: |
3028 | 395 node_help += _(" (DEFAULT: {default})".format(default=default)) |
396 pubsub_group.add_argument("-n", "--node", default='', help=node_help) | |
2532 | 397 |
398 if flags.single_item: | |
3028 | 399 item_help = ("item to retrieve") |
2552
38e1e29c48e9
jp (base): added C.ITEM pubsub flag when --item is required
Goffi <goffi@goffi.org>
parents:
2550
diff
changeset
|
400 if not flags.item: |
3028 | 401 default = defaults.pop('item', _('last item')) |
2552
38e1e29c48e9
jp (base): added C.ITEM pubsub flag when --item is required
Goffi <goffi@goffi.org>
parents:
2550
diff
changeset
|
402 if default is not None: |
3028 | 403 item_help += _(" (DEFAULT: {default})".format(default=default)) |
404 pubsub_group.add_argument("-i", "--item", default='', | |
2910
b2f323237fce
jp, plugin merge-requests: used u'' as default for item id in pubsub arguments + fixed some required arguments:
Goffi <goffi@goffi.org>
parents:
2775
diff
changeset
|
405 help=item_help) |
3040 | 406 pubsub_group.add_argument( |
407 "-L", "--last-item", action='store_true', help=_('retrieve last item')) | |
2532 | 408 elif flags.multi_items: |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
409 # mutiple items, this activate several features: max-items, RSM, MAM |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
410 # and Orbder-by |
3040 | 411 pubsub_group.add_argument( |
412 "-i", "--item", action='append', dest='items', default=[], | |
413 help=_("items to retrieve (DEFAULT: all)")) | |
2539 | 414 if not flags.no_max: |
2775
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
415 max_group = pubsub_group.add_mutually_exclusive_group() |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
416 # XXX: defaut value for --max-items or --max is set in parse_pubsub_args |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
417 max_group.add_argument( |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
418 "-M", "--max-items", dest="max", type=int, |
3028 | 419 help=_("maximum number of items to get ({no_limit} to get all items)" |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
420 .format(no_limit=C.NO_LIMIT))) |
2775
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
421 # FIXME: it could be possible to no duplicate max (between pubsub |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
422 # max-items and RSM max)should not be duplicated, RSM could be |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
423 # used when available and pubsub max otherwise |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
424 max_group.add_argument( |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
425 "-m", "--max", dest="rsm_max", type=int, |
3028 | 426 help=_("maximum number of items to get per page (DEFAULT: 10)")) |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
427 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
428 # RSM |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
429 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
430 rsm_page_group = pubsub_group.add_mutually_exclusive_group() |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
431 rsm_page_group.add_argument( |
3028 | 432 "-a", "--after", dest="rsm_after", |
433 help=_("find page after this item"), metavar='ITEM_ID') | |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
434 rsm_page_group.add_argument( |
3028 | 435 "-b", "--before", dest="rsm_before", |
436 help=_("find page before this item"), metavar='ITEM_ID') | |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
437 rsm_page_group.add_argument( |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
438 "--index", dest="rsm_index", type=int, |
3600
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
439 help=_("index of the first item to retrieve")) |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
440 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
441 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
442 # MAM |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
443 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
444 pubsub_group.add_argument( |
3028 | 445 "-f", "--filter", dest='mam_filters', nargs=2, |
446 action='append', default=[], help=_("MAM filters to use"), | |
447 metavar=("FILTER_NAME", "VALUE") | |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
448 ) |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
449 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
450 # Order-By |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
451 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
452 # TODO: order-by should be a list to handle several levels of ordering |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
453 # but this is not yet done in SàT (and not really useful with |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
454 # current specifications, as only "creation" and "modification" are |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
455 # available) |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
456 pubsub_group.add_argument( |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
457 "-o", "--order-by", choices=[C.ORDER_BY_CREATION, |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
458 C.ORDER_BY_MODIFICATION], |
3028 | 459 help=_("how items should be ordered")) |
2532 | 460 |
3600
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
461 if flags[C.CACHE]: |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
462 pubsub_group.add_argument( |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
463 "-C", "--no-cache", dest="use_cache", action='store_false', |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
464 help=_("don't use Pubsub cache") |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
465 ) |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
466 |
2615
b4ecbcc2fd08
tools (misc): do not remove flags while using them anymore, instead added "all_used" and "unused" properties in FlagsHandler
Goffi <goffi@goffi.org>
parents:
2614
diff
changeset
|
467 if not flags.all_used: |
3040 | 468 raise exceptions.InternalError('unknown flags: {flags}'.format( |
469 flags=', '.join(flags.unused))) | |
2547
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
470 if defaults: |
3040 | 471 raise exceptions.InternalError(f'unused defaults: {defaults}') |
2532 | 472 |
473 return parent | |
2235
4db836386641
jp: added use_pubsub and use_pubsub_node_req arguments to CommandBase
Goffi <goffi@goffi.org>
parents:
2213
diff
changeset
|
474 |
817 | 475 def add_parser_options(self): |
3040 | 476 self.parser.add_argument( |
477 '--version', | |
478 action='version', | |
479 version=("{name} {version} {copyleft}".format( | |
3555
53fec6309fa3
cli: update constants to use new name
Goffi <goffi@goffi.org>
parents:
3547
diff
changeset
|
480 name = C.APP_NAME, |
3040 | 481 version = self.version, |
482 copyleft = COPYLEFT)) | |
483 ) | |
817 | 484 |
2189
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
485 def register_output(self, type_, name, callback, description="", default=False): |
1950 | 486 if type_ not in C.OUTPUT_TYPES: |
3028 | 487 log.error("Invalid output type {}".format(type_)) |
1950 | 488 return |
489 self._outputs[type_][name] = {'callback': callback, | |
490 'description': description | |
491 } | |
2189
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
492 if default: |
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
493 if type_ in self.default_output: |
3040 | 494 self.disp( |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
495 _('there is already a default output for {type}, ignoring new one') |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
496 .format(type=type_) |
3040 | 497 ) |
2189
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
498 else: |
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
499 self.default_output[type_] = name |
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
500 |
1950 | 501 |
2187
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
502 def parse_output_options(self): |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
503 options = self.command.args.output_opts |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
504 options_dict = {} |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
505 for option in options: |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
506 try: |
3028 | 507 key, value = option.split('=', 1) |
2187
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
508 except ValueError: |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
509 key, value = option, None |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
510 options_dict[key.strip()] = value.strip() if value is not None else None |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
511 return options_dict |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
512 |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
513 def check_output_options(self, accepted_set, options): |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
514 if not accepted_set.issuperset(options): |
3040 | 515 self.disp( |
516 _("The following output options are invalid: {invalid_options}").format( | |
3028 | 517 invalid_options = ', '.join(set(options).difference(accepted_set))), |
2187
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
518 error=True) |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
519 self.quit(C.EXIT_BAD_ARG) |
4ec72927a222
jp (outputs): moved output options parsing and checking to base methods
Goffi <goffi@goffi.org>
parents:
2178
diff
changeset
|
520 |
1950 | 521 def import_plugins(self): |
522 """Automaticaly import commands and outputs in jp | |
523 | |
817 | 524 looks from modules names cmd_*.py in jp path and import them |
525 """ | |
526 path = os.path.dirname(sat_frontends.jp.__file__) | |
1950 | 527 # XXX: outputs must be imported before commands as they are used for arguments |
3040 | 528 for type_, pattern in ((C.PLUGIN_OUTPUT, 'output_*.py'), |
529 (C.PLUGIN_CMD, 'cmd_*.py')): | |
530 modules = ( | |
531 os.path.splitext(module)[0] | |
532 for module in map(os.path.basename, iglob(os.path.join(path, pattern)))) | |
1950 | 533 for module_name in modules: |
2162
c9a67eb5bf72
jp (base): improved module import:
Goffi <goffi@goffi.org>
parents:
2161
diff
changeset
|
534 module_path = "sat_frontends.jp." + module_name |
1950 | 535 try: |
2162
c9a67eb5bf72
jp (base): improved module import:
Goffi <goffi@goffi.org>
parents:
2161
diff
changeset
|
536 module = import_module(module_path) |
1950 | 537 self.import_plugin_module(module, type_) |
2178
b9bfc45cea22
jp (base): added generic errback to CommandBase + show error message on plugin ImportError
Goffi <goffi@goffi.org>
parents:
2168
diff
changeset
|
538 except ImportError as e: |
3040 | 539 self.disp( |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
540 _("Can't import {module_path} plugin, ignoring it: {e}") |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
541 .format(module_path=module_path, e=e), |
3040 | 542 error=True) |
2162
c9a67eb5bf72
jp (base): improved module import:
Goffi <goffi@goffi.org>
parents:
2161
diff
changeset
|
543 except exceptions.CancelError: |
1950 | 544 continue |
2162
c9a67eb5bf72
jp (base): improved module import:
Goffi <goffi@goffi.org>
parents:
2161
diff
changeset
|
545 except exceptions.MissingModule as e: |
3028 | 546 self.disp(_("Missing module for plugin {name}: {missing}".format( |
2162
c9a67eb5bf72
jp (base): improved module import:
Goffi <goffi@goffi.org>
parents:
2161
diff
changeset
|
547 name = module_path, |
2188
052d560d0dce
jp (base): replaced log.warning by stderr prints
Goffi <goffi@goffi.org>
parents:
2187
diff
changeset
|
548 missing = e)), error=True) |
2162
c9a67eb5bf72
jp (base): improved module import:
Goffi <goffi@goffi.org>
parents:
2161
diff
changeset
|
549 |
0 | 550 |
1950 | 551 def import_plugin_module(self, module, type_): |
552 """add commands or outpus from a module to jp | |
817 | 553 |
1950 | 554 @param module: module containing commands or outputs |
555 @param type_(str): one of C_PLUGIN_* | |
817 | 556 """ |
557 try: | |
1950 | 558 class_names = getattr(module, '__{}__'.format(type_)) |
817 | 559 except AttributeError: |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
560 log.disp( |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
561 _("Invalid plugin module [{type}] {module}") |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
562 .format(type=type_, module=module), |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
563 error=True) |
817 | 564 raise ImportError |
1950 | 565 else: |
566 for class_name in class_names: | |
567 cls = getattr(module, class_name) | |
568 cls(self) | |
817 | 569 |
2532 | 570 def get_xmpp_uri_from_http(self, http_url): |
571 """parse HTML page at http(s) URL, and looks for xmpp: uri""" | |
572 if http_url.startswith('https'): | |
3028 | 573 scheme = 'https' |
2532 | 574 elif http_url.startswith('http'): |
3028 | 575 scheme = 'http' |
2532 | 576 else: |
3028 | 577 raise exceptions.InternalError('An HTTP scheme is expected in this method') |
3040 | 578 self.disp(f"{scheme.upper()} URL found, trying to find associated xmpp: URI", 1) |
2532 | 579 # HTTP URL, we try to find xmpp: links |
580 try: | |
581 from lxml import etree | |
582 except ImportError: | |
3040 | 583 self.disp( |
584 "lxml module must be installed to use http(s) scheme, please install it " | |
585 "with \"pip install lxml\"", | |
586 error=True) | |
2672 | 587 self.quit(1) |
3028 | 588 import urllib.request, urllib.error, urllib.parse |
2532 | 589 parser = etree.HTMLParser() |
590 try: | |
3028 | 591 root = etree.parse(urllib.request.urlopen(http_url), parser) |
2532 | 592 except etree.XMLSyntaxError as e: |
3028 | 593 self.disp(_("Can't parse HTML page : {msg}").format(msg=e)) |
2532 | 594 links = [] |
595 else: | |
596 links = root.xpath("//link[@rel='alternate' and starts-with(@href, 'xmpp:')]") | |
597 if not links: | |
3040 | 598 self.disp( |
599 _('Could not find alternate "xmpp:" URI, can\'t find associated XMPP ' | |
600 'PubSub node/item'), | |
601 error=True) | |
2672 | 602 self.quit(1) |
2532 | 603 xmpp_uri = links[0].get('href') |
604 return xmpp_uri | |
605 | |
606 def parse_pubsub_args(self): | |
607 if self.args.pubsub_url is not None: | |
608 url = self.args.pubsub_url | |
609 | |
610 if url.startswith('http'): | |
611 # http(s) URL, we try to retrieve xmpp one from there | |
612 url = self.get_xmpp_uri_from_http(url) | |
613 | |
614 try: | |
615 uri_data = uri.parseXMPPUri(url) | |
616 except ValueError: | |
3028 | 617 self.parser.error(_('invalid XMPP URL: {url}').format(url=url)) |
2532 | 618 else: |
3028 | 619 if uri_data['type'] == 'pubsub': |
2532 | 620 # URL is alright, we only set data not already set by other options |
621 if not self.args.service: | |
3028 | 622 self.args.service = uri_data['path'] |
2532 | 623 if not self.args.node: |
3028 | 624 self.args.node = uri_data['node'] |
625 uri_item = uri_data.get('item') | |
2532 | 626 if uri_item: |
2556
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
627 # there is an item in URI |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
628 # we use it only if item is not already set |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
629 # and item_last is not used either |
2532 | 630 try: |
2556
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
631 item = self.args.item |
2532 | 632 except AttributeError: |
2609
75d2ac872965
jp (base): do not crash when item is specified (e.g. in URL) but not needed in command, but display a message on stderr.
Goffi <goffi@goffi.org>
parents:
2588
diff
changeset
|
633 try: |
75d2ac872965
jp (base): do not crash when item is specified (e.g. in URL) but not needed in command, but display a message on stderr.
Goffi <goffi@goffi.org>
parents:
2588
diff
changeset
|
634 items = self.args.items |
75d2ac872965
jp (base): do not crash when item is specified (e.g. in URL) but not needed in command, but display a message on stderr.
Goffi <goffi@goffi.org>
parents:
2588
diff
changeset
|
635 except AttributeError: |
3040 | 636 self.disp( |
637 _("item specified in URL but not needed in command, " | |
638 "ignoring it"), | |
639 error=True) | |
2609
75d2ac872965
jp (base): do not crash when item is specified (e.g. in URL) but not needed in command, but display a message on stderr.
Goffi <goffi@goffi.org>
parents:
2588
diff
changeset
|
640 else: |
75d2ac872965
jp (base): do not crash when item is specified (e.g. in URL) but not needed in command, but display a message on stderr.
Goffi <goffi@goffi.org>
parents:
2588
diff
changeset
|
641 if not items: |
75d2ac872965
jp (base): do not crash when item is specified (e.g. in URL) but not needed in command, but display a message on stderr.
Goffi <goffi@goffi.org>
parents:
2588
diff
changeset
|
642 self.args.items = [uri_item] |
2532 | 643 else: |
2556
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
644 if not item: |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
645 try: |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
646 item_last = self.args.item_last |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
647 except AttributeError: |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
648 item_last = False |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
649 if not item_last: |
340128e0b354
jp (base): fixed URI's item with use_pubsub
Goffi <goffi@goffi.org>
parents:
2552
diff
changeset
|
650 self.args.item = uri_item |
2532 | 651 else: |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
652 self.parser.error( |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
653 _('XMPP URL is not a pubsub one: {url}').format(url=url) |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
654 ) |
2532 | 655 flags = self.args._cmd._pubsub_flags |
656 # we check required arguments here instead of using add_arguments' required option | |
657 # because the required argument can be set in URL | |
658 if C.SERVICE in flags and not self.args.service: | |
3028 | 659 self.parser.error(_("argument -s/--service is required")) |
2532 | 660 if C.NODE in flags and not self.args.node: |
3028 | 661 self.parser.error(_("argument -n/--node is required")) |
2552
38e1e29c48e9
jp (base): added C.ITEM pubsub flag when --item is required
Goffi <goffi@goffi.org>
parents:
2550
diff
changeset
|
662 if C.ITEM in flags and not self.args.item: |
3028 | 663 self.parser.error(_("argument -i/--item is required")) |
2532 | 664 |
665 # FIXME: mutually groups can't be nested in a group and don't support title | |
666 # so we check conflict here. This may be fixed in Python 3, to be checked | |
667 try: | |
668 if self.args.item and self.args.item_last: | |
3040 | 669 self.parser.error( |
670 _("--item and --item-last can't be used at the same time")) | |
2532 | 671 except AttributeError: |
672 pass | |
673 | |
2775
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
674 try: |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
675 max_items = self.args.max |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
676 rsm_max = self.args.rsm_max |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
677 except AttributeError: |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
678 pass |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
679 else: |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
680 # we need to set a default value for max, but we need to know if we want |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
681 # to use pubsub's max or RSM's max. The later is used if any RSM or MAM |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
682 # argument is set |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
683 if max_items is None and rsm_max is None: |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
684 to_check = ('mam_filters', 'rsm_max', 'rsm_after', 'rsm_before', |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
685 'rsm_index') |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
686 if any((getattr(self.args, name) for name in to_check)): |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
687 # we use RSM |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
688 self.args.rsm_max = 10 |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
689 else: |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
690 # we use pubsub without RSM |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
691 self.args.max = 10 |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
692 if self.args.max is None: |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
693 self.args.max = C.NO_LIMIT |
2dfd5b1d39df
jp (base): fixed default values for --max-items and --max when using pubsub
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
694 |
3040 | 695 async def main(self, args, namespace): |
1884
0fe69871b71f
jp: moved KeyboardInterrupt catch one level higher, so it is also catched if the loop is not started
Goffi <goffi@goffi.org>
parents:
1872
diff
changeset
|
696 try: |
3040 | 697 await self.bridge.bridgeConnect() |
698 except Exception as e: | |
699 if isinstance(e, exceptions.BridgeExceptionNoService): | |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
700 print(_("Can't connect to SàT backend, are you sure it's launched ?")) |
3490
509f7a1c67dc
frontends: use new EXIT_BACKEND_NOT_FOUND exit code:
Goffi <goffi@goffi.org>
parents:
3486
diff
changeset
|
701 self.quit(C.EXIT_BACKEND_NOT_FOUND, raise_exc=False) |
3040 | 702 elif isinstance(e, exceptions.BridgeInitError): |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
703 print(_("Can't init bridge")) |
3490
509f7a1c67dc
frontends: use new EXIT_BACKEND_NOT_FOUND exit code:
Goffi <goffi@goffi.org>
parents:
3486
diff
changeset
|
704 self.quit(C.EXIT_BRIDGE_ERROR, raise_exc=False) |
3040 | 705 else: |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
706 print( |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
707 _("Error while initialising bridge: {e}").format(e=e) |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
708 ) |
3490
509f7a1c67dc
frontends: use new EXIT_BACKEND_NOT_FOUND exit code:
Goffi <goffi@goffi.org>
parents:
3486
diff
changeset
|
709 self.quit(C.EXIT_BRIDGE_ERROR, raise_exc=False) |
3040 | 710 return |
3636
43542cf32e5a
cli: call `bridge.getReady()` after bridge connection
Goffi <goffi@goffi.org>
parents:
3568
diff
changeset
|
711 await self.bridge.getReady() |
3040 | 712 self.version = await self.bridge.getVersion() |
713 self._bridgeConnected() | |
714 self.import_plugins() | |
715 try: | |
716 self.args = self.parser.parse_args(args, namespace=None) | |
717 if self.args._cmd._use_pubsub: | |
718 self.parse_pubsub_args() | |
719 await self.args._cmd.run() | |
720 except SystemExit as e: | |
721 self.quit(e.code, raise_exc=False) | |
722 return | |
723 except QuitException: | |
724 return | |
817 | 725 |
3481
7892585b7e17
core (setup), jp, primitivus: update console scripts + classifiers:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
726 def _run(self, args=None, namespace=None): |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
727 self.loop = JPLoop() |
3040 | 728 self.loop.run(self, args, namespace) |
0 | 729 |
3481
7892585b7e17
core (setup), jp, primitivus: update console scripts + classifiers:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
730 @classmethod |
7892585b7e17
core (setup), jp, primitivus: update console scripts + classifiers:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
731 def run(cls): |
7892585b7e17
core (setup), jp, primitivus: update console scripts + classifiers:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
732 cls()._run() |
7892585b7e17
core (setup), jp, primitivus: update console scripts + classifiers:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
733 |
3040 | 734 def _read_stdin(self, stdin_fut): |
735 """Callback called by ainput to read stdin""" | |
736 line = sys.stdin.readline() | |
737 if line: | |
738 stdin_fut.set_result(line.rstrip(os.linesep)) | |
739 else: | |
740 stdin_fut.set_exception(EOFError()) | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
741 |
3040 | 742 async def ainput(self, msg=''): |
743 """Asynchronous version of buildin "input" function""" | |
3407
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
744 self.disp(msg, end=' ') |
3040 | 745 sys.stdout.flush() |
746 loop = asyncio.get_running_loop() | |
747 stdin_fut = loop.create_future() | |
748 loop.add_reader(sys.stdin, self._read_stdin, stdin_fut) | |
749 return await stdin_fut | |
750 | |
3409 | 751 async def confirm(self, message): |
752 """Request user to confirm action, return answer as boolean""" | |
753 res = await self.ainput(f"{message} (y/N)? ") | |
754 return res in ("y", "Y") | |
755 | |
3040 | 756 async def confirmOrQuit(self, message, cancel_message=_("action cancelled by user")): |
2550
1d754bc14381
jp (base): new confirmOrQuit helper method to ask confirmation to user, and quit if he cancel
Goffi <goffi@goffi.org>
parents:
2547
diff
changeset
|
757 """Request user to confirm action, and quit if he doesn't""" |
3409 | 758 confirmed = await self.confirm(message) |
759 if not confirmed: | |
2550
1d754bc14381
jp (base): new confirmOrQuit helper method to ask confirmation to user, and quit if he cancel
Goffi <goffi@goffi.org>
parents:
2547
diff
changeset
|
760 self.disp(cancel_message) |
1d754bc14381
jp (base): new confirmOrQuit helper method to ask confirmation to user, and quit if he cancel
Goffi <goffi@goffi.org>
parents:
2547
diff
changeset
|
761 self.quit(C.EXIT_USER_CANCELLED) |
1d754bc14381
jp (base): new confirmOrQuit helper method to ask confirmation to user, and quit if he cancel
Goffi <goffi@goffi.org>
parents:
2547
diff
changeset
|
762 |
3040 | 763 def quitFromSignal(self, exit_code=0): |
764 r"""Same as self.quit, but from a signal handler | |
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
|
765 |
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
|
766 /!\: 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
|
767 """ |
1918
01d56efd488b
jp: fixed traceback shown on a normal quit when a progression is finished
Goffi <goffi@goffi.org>
parents:
1884
diff
changeset
|
768 # XXX: python-dbus will show a traceback if we exit in a signal handler |
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
|
769 # so we use this little timeout trick to avoid it |
3040 | 770 self.loop.call_later(0, self.quit, exit_code) |
771 | |
772 def quit(self, exit_code=0, raise_exc=True): | |
773 """Terminate the execution with specified exit_code | |
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
|
774 |
3040 | 775 This will stop the loop. |
776 @param exit_code(int): code to return when quitting the program | |
777 @param raise_exp(boolean): if True raise a QuitException to stop code execution | |
778 The default value should be used most of time. | |
779 """ | |
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
|
780 # 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
|
781 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
|
782 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
|
783 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
|
784 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
|
785 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
|
786 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
|
787 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
|
788 |
3040 | 789 self.loop.quit(exit_code) |
790 if raise_exc: | |
791 raise QuitException | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
792 |
3040 | 793 async def check_jids(self, jids): |
814 | 794 """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
|
795 |
817 | 796 @param profile: profile name |
797 @param jids: list of jids | |
798 @return: List of jids | |
799 | |
814 | 800 """ |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
801 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
|
802 nodes2jid = {} |
393 | 803 |
3765
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
804 try: |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
805 contacts = await self.bridge.getContacts(self.profile) |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
806 except BridgeException as e: |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
807 if e.classname == "AttributeError": |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
808 # we may get an AttributeError if we use a component profile |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
809 # as components don't have roster |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
810 contacts = [] |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
811 else: |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
812 raise e |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
813 |
ea204216a505
CLI: don't fail when calling `getContacts` with a component profile
Goffi <goffi@goffi.org>
parents:
3709
diff
changeset
|
814 for contact in contacts: |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
815 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
|
816 _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
|
817 try: |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
818 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
|
819 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
|
820 pass |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
821 |
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
822 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
|
823 nodes2jid[_jid.node.lower()] = jid_s |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
824 |
817 | 825 def expand_jid(jid): |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
826 _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
|
827 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
|
828 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
|
829 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
|
830 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
|
831 else: |
b7c4bb2c0668
jp: - better expandJid: roster's jids' nodes are used after names to expand jid
Goffi <goffi@goffi.org>
parents:
480
diff
changeset
|
832 expanded = jid |
2588 | 833 return expanded |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
834 |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
835 def check(jid): |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
836 if not jid.is_valid: |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
837 log.error (_("%s is not a valid JID !"), jid) |
817 | 838 self.quit(1) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
839 |
814 | 840 dest_jids=[] |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
841 try: |
814 | 842 for i in range(len(jids)): |
817 | 843 dest_jids.append(expand_jid(jids[i])) |
814 | 844 check(dest_jids[i]) |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
845 except AttributeError: |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
846 pass |
0 | 847 |
814 | 848 return dest_jids |
0 | 849 |
3049
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
850 async def a_pwd_input(self, msg=''): |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
851 """Like ainput but with echo disabled (useful for passwords)""" |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
852 # we disable echo, code adapted from getpass standard module which has been |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
853 # written by Piers Lauder (original), Guido van Rossum (Windows support and |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
854 # cleanup) and Gregory P. Smith (tty support & GetPassWarning), a big thanks |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
855 # to them (and for all the amazing work on Python). |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
856 stdin_fd = sys.stdin.fileno() |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
857 old = termios.tcgetattr(sys.stdin) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
858 new = old[:] |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
859 new[3] &= ~termios.ECHO |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
860 tcsetattr_flags = termios.TCSAFLUSH |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
861 if hasattr(termios, 'TCSASOFT'): |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
862 tcsetattr_flags |= termios.TCSASOFT |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
863 try: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
864 termios.tcsetattr(stdin_fd, tcsetattr_flags, new) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
865 pwd = await self.ainput(msg=msg) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
866 finally: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
867 termios.tcsetattr(stdin_fd, tcsetattr_flags, old) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
868 sys.stderr.flush() |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
869 self.disp('') |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
870 return pwd |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
871 |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
872 async def connectOrPrompt(self, method, err_msg=None): |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
873 """Try to connect/start profile session and prompt for password if needed |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
874 |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
875 @param method(callable): bridge method to either connect or start profile session |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
876 It will be called with password as sole argument, use lambda to do the call |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
877 properly |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
878 @param err_msg(str): message to show if connection fail |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
879 """ |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
880 password = self.args.pwd |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
881 while True: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
882 try: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
883 await method(password or '') |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
884 except Exception as e: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
885 if ((isinstance(e, BridgeException) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
886 and e.classname == 'PasswordError' |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
887 and self.args.pwd is None)): |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
888 if password is not None: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
889 self.disp(A.color(C.A_WARNING, _("invalid password"))) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
890 password = await self.a_pwd_input( |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
891 _("please enter profile password:")) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
892 else: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
893 self.disp(err_msg.format(profile=self.profile, e=e), error=True) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
894 self.quit(C.EXIT_ERROR) |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
895 else: |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
896 break |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
897 |
3040 | 898 async def connect_profile(self): |
899 """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
|
900 |
817 | 901 @exit: - 1 when profile is not connected and --connect is not set |
902 - 1 when the profile doesn't exists | |
903 - 1 when there is a connection error | |
904 """ | |
905 # FIXME: need better exit codes | |
906 | |
3040 | 907 self.profile = await self.bridge.profileNameGet(self.args.profile) |
0 | 908 |
817 | 909 if not self.profile: |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
910 log.error( |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
911 _("The profile [{profile}] doesn't exist") |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
912 .format(profile=self.args.profile) |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
913 ) |
3040 | 914 self.quit(C.EXIT_ERROR) |
817 | 915 |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
916 try: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
917 start_session = self.args.start_session |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
918 except AttributeError: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
919 pass |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
920 else: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
921 if start_session: |
3049
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
922 await self.connectOrPrompt( |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
923 lambda pwd: self.bridge.profileStartSession(pwd, self.profile), |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
924 err_msg="Can't start {profile}'s session: {e}" |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
925 ) |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
926 return |
3040 | 927 elif not await self.bridge.profileIsSessionStarted(self.profile): |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
928 if not self.args.connect: |
3040 | 929 self.disp(_( |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
930 "Session for [{profile}] is not started, please start it " |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
931 "before using jp, or use either --start-session or --connect " |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
932 "option" |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
933 .format(profile=self.profile) |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
934 ), error=True) |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
935 self.quit(1) |
2692
7d4679ee7ded
jp (base): fixed connection when start_session arg exists but is False
Goffi <goffi@goffi.org>
parents:
2672
diff
changeset
|
936 elif not getattr(self.args, "connect", False): |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
937 return |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
938 |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
939 |
1401
265ff2bd8d67
jp: fixed crash on commands using profile without "connect" option
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
940 if not hasattr(self.args, 'connect'): |
3040 | 941 # a profile can be present without connect option (e.g. on profile |
942 # creation/deletion) | |
1401
265ff2bd8d67
jp: fixed crash on commands using profile without "connect" option
Goffi <goffi@goffi.org>
parents:
1396
diff
changeset
|
943 return |
1588
823a385235ef
jp: fixed bad --connect option check
Goffi <goffi@goffi.org>
parents:
1544
diff
changeset
|
944 elif self.args.connect is True: # if connection is asked, we connect the profile |
3049
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
945 await self.connectOrPrompt( |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
946 lambda pwd: self.bridge.connect(self.profile, pwd, {}), |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
947 err_msg = 'Can\'t connect profile "{profile!s}": {e}' |
9839ce068140
jp: password is now prompted if needed:
Goffi <goffi@goffi.org>
parents:
3046
diff
changeset
|
948 ) |
814 | 949 return |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
950 else: |
3040 | 951 if not await self.bridge.isConnected(self.profile): |
952 log.error( | |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
953 _("Profile [{profile}] is not connected, please connect it " |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
954 "before using jp, or use --connect option") |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
955 .format(profile=self.profile) |
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
956 ) |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
957 self.quit(1) |
0 | 958 |
3040 | 959 async 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
|
960 """Return the full jid if possible (add main resource when find a bare jid)""" |
3408
19bc03743aeb
jp (file/send): don't add main resource to bare jid anymore:
Goffi <goffi@goffi.org>
parents:
3407
diff
changeset
|
961 # TODO: to be removed, bare jid should work with all commands, notably for file |
19bc03743aeb
jp (file/send): don't add main resource to bare jid anymore:
Goffi <goffi@goffi.org>
parents:
3407
diff
changeset
|
962 # as backend now handle jingles message initiation |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
963 _jid = JID(param_jid) |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
964 if not _jid.resource: |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
965 #if the resource is not given, we try to add the main resource |
3040 | 966 main_resource = await self.bridge.getMainResource(param_jid, self.profile) |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
967 if main_resource: |
3040 | 968 return f"{_jid.bare}/{main_resource}" |
401
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
969 return param_jid |
b2caa2615c4c
jp roster name manegement + Pipe transfer
Goffi <goffi@goffi.org>
parents:
393
diff
changeset
|
970 |
814 | 971 |
817 | 972 class CommandBase(object): |
814 | 973 |
2155 | 974 def __init__(self, host, name, use_profile=True, use_output=False, extra_outputs=None, |
1950 | 975 need_connect=None, help=None, **kwargs): |
2098
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
976 """Initialise CommandBase |
e0066920a661
primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Goffi <goffi@goffi.org>
parents:
2086
diff
changeset
|
977 |
817 | 978 @param host: Jp instance |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
979 @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
|
980 @param use_profile(bool): if True, add profile selection/connection commands |
2114
dc5d214f0a3b
jp (info/session): added a command to get data on current session
Goffi <goffi@goffi.org>
parents:
2098
diff
changeset
|
981 @param use_output(bool, unicode): if not False, add --output option |
2155 | 982 @param extra_outputs(dict): list of command specific outputs: |
983 key is output name ("default" to use as main output) | |
3040 | 984 value is a callable which will format the output (data will be used as only |
985 argument) | |
2155 | 986 if a key already exists with normal outputs, the extra one will be used |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
987 @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
|
988 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
|
989 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
|
990 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
|
991 @param help(unicode): help message to display |
817 | 992 @param **kwargs: args passed to ArgumentParser |
1950 | 993 use_* are handled directly, they can be: |
994 - use_progress(bool): if True, add progress bar activation option | |
995 progress* signals will be handled | |
996 - use_verbose(bool): if True, add verbosity option | |
2532 | 997 - use_pubsub(bool): if True, add pubsub options |
998 mandatory arguments are controlled by pubsub_req | |
999 - use_draft(bool): if True, add draft handling options | |
1000 ** other arguments ** | |
3040 | 1001 - pubsub_flags(iterable[unicode]): tuple of flags to set pubsub options, |
1002 can be: | |
2532 | 1003 C.SERVICE: service is required |
1004 C.NODE: node is required | |
2614
a5b96950b81a
jp (event): fixed crash on missing item in get and inviteeGet by making it mandatory.
Goffi <goffi@goffi.org>
parents:
2609
diff
changeset
|
1005 C.ITEM: item is required |
2532 | 1006 C.SINGLE_ITEM: only one item is allowed |
814 | 1007 """ |
817 | 1008 try: # If we have subcommands, host is a CommandBase and we need to use host.host |
1009 self.host = host.host | |
1010 except AttributeError: | |
1011 self.host = host | |
1012 | |
1950 | 1013 # --profile option |
817 | 1014 parents = kwargs.setdefault('parents', set()) |
1015 if use_profile: | |
3040 | 1016 # self.host.parents['profile'] is an ArgumentParser with profile connection |
1017 # arguments | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
1018 if need_connect is None: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
1019 need_connect = True |
3040 | 1020 parents.add( |
1021 self.host.parents['profile' if need_connect else 'profile_session']) | |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
1022 else: |
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
1023 assert need_connect is None |
1860
afc7f6328394
jp (base): use need_connect attribue to detect if connection is needed instead of self.args.profile, as profile argument can be used by any command even if use_profile is False
Goffi <goffi@goffi.org>
parents:
1840
diff
changeset
|
1024 self.need_connect = need_connect |
afc7f6328394
jp (base): use need_connect attribue to detect if connection is needed instead of self.args.profile, as profile argument can be used by any command even if use_profile is False
Goffi <goffi@goffi.org>
parents:
1840
diff
changeset
|
1025 # from this point, self.need_connect is None if connection is not needed at all |
afc7f6328394
jp (base): use need_connect attribue to detect if connection is needed instead of self.args.profile, as profile argument can be used by any command even if use_profile is False
Goffi <goffi@goffi.org>
parents:
1840
diff
changeset
|
1026 # False if session starting is needed, and True if full connection is needed |
1594
313f2bb7841b
jp: profile session can now be started without connection:
Goffi <goffi@goffi.org>
parents:
1588
diff
changeset
|
1027 |
1950 | 1028 # --output option |
1029 if use_output: | |
2155 | 1030 if extra_outputs is None: |
1031 extra_outputs = {} | |
1032 self.extra_outputs = extra_outputs | |
1950 | 1033 if use_output == True: |
1034 use_output = C.OUTPUT_TEXT | |
1035 assert use_output in C.OUTPUT_TYPES | |
1036 self._output_type = use_output | |
1037 output_parent = argparse.ArgumentParser(add_help=False) | |
2155 | 1038 choices = set(self.host.getOutputChoices(use_output)) |
1039 choices.update(extra_outputs) | |
1950 | 1040 if not choices: |
3040 | 1041 raise exceptions.InternalError( |
1042 "No choice found for {} output type".format(use_output)) | |
2189
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
1043 try: |
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
1044 default = self.host.default_output[use_output] |
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
1045 except KeyError: |
3028 | 1046 if 'default' in choices: |
1047 default = 'default' | |
1048 elif 'simple' in choices: | |
1049 default = 'simple' | |
2189
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
1050 else: |
a25a256688e2
jp (base): output can now specify a default when registering
Goffi <goffi@goffi.org>
parents:
2188
diff
changeset
|
1051 default = list(choices)[0] |
3040 | 1052 output_parent.add_argument( |
1053 '--output', '-O', choices=sorted(choices), default=default, | |
1054 help=_("select output format (default: {})".format(default))) | |
1055 output_parent.add_argument( | |
1056 '--output-option', '--oo', action="append", dest='output_opts', | |
1057 default=[], help=_("output specific option")) | |
1950 | 1058 parents.add(output_parent) |
2155 | 1059 else: |
1060 assert extra_outputs is None | |
817 | 1061 |
2532 | 1062 self._use_pubsub = kwargs.pop('use_pubsub', False) |
1063 if self._use_pubsub: | |
2538
0a22dc80d671
jp (base): fixed use_pubsub when pubsub_flags is not needed
Goffi <goffi@goffi.org>
parents:
2532
diff
changeset
|
1064 flags = kwargs.pop('pubsub_flags', []) |
2547
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
1065 defaults = kwargs.pop('pubsub_defaults', {}) |
2d69a0afe039
jp: new argument pubsub_default can be used in Commands to replace default value in help string
Goffi <goffi@goffi.org>
parents:
2539
diff
changeset
|
1066 parents.add(self.host.make_pubsub_group(flags, defaults)) |
2532 | 1067 self._pubsub_flags = flags |
2235
4db836386641
jp: added use_pubsub and use_pubsub_node_req arguments to CommandBase
Goffi <goffi@goffi.org>
parents:
2213
diff
changeset
|
1068 |
1950 | 1069 # other common options |
3028 | 1070 use_opts = {k:v for k,v in kwargs.items() if k.startswith('use_')} |
1071 for param, do_use in use_opts.items(): | |
1950 | 1072 opt=param[4:] # if param is use_verbose, opt is verbose |
1073 if opt not in self.host.parents: | |
3028 | 1074 raise exceptions.InternalError("Unknown parent option {}".format(opt)) |
1950 | 1075 del kwargs[param] |
1076 if do_use: | |
1077 parents.add(self.host.parents[opt]) | |
1600 | 1078 |
817 | 1079 self.parser = host.subparsers.add_parser(name, help=help, **kwargs) |
1080 if hasattr(self, "subcommands"): | |
3040 | 1081 self.subparsers = self.parser.add_subparsers(dest='subcommand', required=True) |
817 | 1082 else: |
2532 | 1083 self.parser.set_defaults(_cmd=self) |
817 | 1084 self.add_parser_options() |
1085 | |
1086 @property | |
3046 | 1087 def sat_conf(self): |
1088 return self.host.sat_conf | |
1089 | |
1090 @property | |
817 | 1091 def args(self): |
1092 return self.host.args | |
1093 | |
1094 @property | |
1095 def profile(self): | |
1096 return self.host.profile | |
1097 | |
1098 @property | |
2490
b4bf282d6354
jp (base): added verbosity property to CommandBase
Goffi <goffi@goffi.org>
parents:
2486
diff
changeset
|
1099 def verbosity(self): |
b4bf282d6354
jp (base): added verbosity property to CommandBase
Goffi <goffi@goffi.org>
parents:
2486
diff
changeset
|
1100 return self.host.verbosity |
b4bf282d6354
jp (base): added verbosity property to CommandBase
Goffi <goffi@goffi.org>
parents:
2486
diff
changeset
|
1101 |
b4bf282d6354
jp (base): added verbosity property to CommandBase
Goffi <goffi@goffi.org>
parents:
2486
diff
changeset
|
1102 @property |
817 | 1103 def progress_id(self): |
1104 return self.host.progress_id | |
814 | 1105 |
3040 | 1106 async def set_progress_id(self, progress_id): |
1107 return await self.host.set_progress_id(progress_id) | |
817 | 1108 |
3040 | 1109 async def progressStartedHandler(self, uid, metadata, profile): |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1110 if profile != self.profile: |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1111 return |
1642
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1112 if self.progress_id is None: |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1113 # the progress started message can be received before the id |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1114 # so we keep progressStarted signals in cache to replay they |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1115 # when the progress_id is received |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1116 cache_data = (self.progressStartedHandler, uid, metadata, profile) |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1117 try: |
3040 | 1118 cache = self.host.progress_ids_cache |
1642
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1119 except AttributeError: |
3040 | 1120 cache = self.host.progress_ids_cache = [] |
1121 cache.append(cache_data) | |
1642
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1122 else: |
7ec7ce9cdc4c
jp (base): progressStarted signals are cached until progress_id is known, this avoid missing the progression if we have the signal before the id.
Goffi <goffi@goffi.org>
parents:
1641
diff
changeset
|
1123 if self.host.watch_progress and uid == self.progress_id: |
3040 | 1124 await self.onProgressStarted(metadata) |
1125 while True: | |
1126 await asyncio.sleep(PROGRESS_DELAY) | |
1127 cont = await self.progressUpdate() | |
1128 if not cont: | |
1129 break | |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1130 |
3040 | 1131 async def progressFinishedHandler(self, uid, metadata, profile): |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1132 if profile != self.profile: |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1133 return |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1134 if uid == self.progress_id: |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1135 try: |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1136 self.host.pbar.finish() |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1137 except AttributeError: |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1138 pass |
3040 | 1139 await self.onProgressFinished(metadata) |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1140 if self.host.quit_on_progress_end: |
1918
01d56efd488b
jp: fixed traceback shown on a normal quit when a progression is finished
Goffi <goffi@goffi.org>
parents:
1884
diff
changeset
|
1141 self.host.quitFromSignal() |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1142 |
3040 | 1143 async def progressErrorHandler(self, uid, message, profile): |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1144 if profile != self.profile: |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1145 return |
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1146 if uid == self.progress_id: |
1641
44a14f83e64b
jp (base): fixed verbose option + there is a new line on ProgressErrorHandler only if the progress bar is actually displayed
Goffi <goffi@goffi.org>
parents:
1627
diff
changeset
|
1147 if self.args.progress: |
44a14f83e64b
jp (base): fixed verbose option + there is a new line on ProgressErrorHandler only if the progress bar is actually displayed
Goffi <goffi@goffi.org>
parents:
1627
diff
changeset
|
1148 self.disp('') # progress is not finished, so we skip a line |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1149 if self.host.quit_on_progress_end: |
3040 | 1150 await self.onProgressError(message) |
1151 self.host.quitFromSignal(C.EXIT_ERROR) | |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1152 |
3040 | 1153 async def progressUpdate(self): |
1154 """This method is continualy called to update the progress bar | |
1155 | |
1156 @return (bool): False to stop being called | |
1157 """ | |
1158 data = await self.host.bridge.progressGet(self.progress_id, self.profile) | |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1159 if data: |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1160 try: |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1161 size = data['size'] |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1162 except KeyError: |
3040 | 1163 self.disp(_("file size is not known, we can't show a progress bar"), 1, |
1164 error=True) | |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1165 return False |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1166 if self.host.pbar is None: |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1167 #first answer, we must construct the bar |
3040 | 1168 |
1169 # if the instance has a pbar_template attribute, it is used has model, | |
1170 # else default one is used | |
1171 # template is a list of part, where part can be either a str to show directly | |
1172 # or a list where first argument is a name of a progressbar widget, and others | |
1173 # are used as widget arguments | |
1174 try: | |
1175 template = self.pbar_template | |
1176 except AttributeError: | |
1177 template = [ | |
1178 _("Progress: "), ["Percentage"], " ", ["Bar"], " ", | |
1179 ["FileTransferSpeed"], " ", ["ETA"] | |
1180 ] | |
1181 | |
1182 widgets = [] | |
1183 for part in template: | |
1184 if isinstance(part, str): | |
1185 widgets.append(part) | |
1186 else: | |
1187 widget = getattr(progressbar, part.pop(0)) | |
1188 widgets.append(widget(*part)) | |
1189 | |
1190 self.host.pbar = progressbar.ProgressBar(max_value=int(size), widgets=widgets) | |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1191 self.host.pbar.start() |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1192 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1193 self.host.pbar.update(int(data['position'])) |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1194 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1195 elif self.host.pbar is not None: |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1196 return False |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1197 |
3040 | 1198 await self.onProgressUpdate(data) |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1199 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1200 return True |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1201 |
3040 | 1202 async def onProgressStarted(self, metadata): |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1203 """Called when progress has just started |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1204 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1205 can be overidden by a command |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1206 @param metadata(dict): metadata as sent by bridge.progressStarted |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1207 """ |
3028 | 1208 self.disp(_("Operation started"), 2) |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1209 |
3040 | 1210 async def onProgressUpdate(self, metadata): |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1211 """Method called on each progress updata |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1212 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1213 can be overidden by a command to handle progress metadata |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1214 @para metadata(dict): metadata as returned by bridge.progressGet |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1215 """ |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1216 pass |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1217 |
3040 | 1218 async def onProgressFinished(self, metadata): |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1219 """Called when progress has just finished |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1220 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1221 can be overidden by a command |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1222 @param metadata(dict): metadata as sent by bridge.progressFinished |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1223 """ |
3028 | 1224 self.disp(_("Operation successfully finished"), 2) |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1225 |
3040 | 1226 async def onProgressError(self, e): |
1832
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1227 """Called when a progress failed |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1228 |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1229 @param error_msg(unicode): error message as sent by bridge.progressError |
39545dc527a1
jp: an onProgressUpdate method is now called on each progress update, allowing to handle metadata
Goffi <goffi@goffi.org>
parents:
1766
diff
changeset
|
1230 """ |
3568
04283582966f
core, frontends: fix invalid translatable strings.
Goffi <goffi@goffi.org>
parents:
3555
diff
changeset
|
1231 self.disp(_("Error while doing operation: {e}").format(e=e), error=True) |
1627
5a641e7b858a
jp (base, file): use of new progress API. Progress callbacks are managed through CommandBase.onProgress* method instead of host attributes.
Goffi <goffi@goffi.org>
parents:
1623
diff
changeset
|
1232 |
3407
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
1233 def disp(self, msg, verbosity=0, error=False, end='\n'): |
2f0be2b7de68
jp: replace `no_lf` argument by `end` in `disp` (same as in `print`)
Goffi <goffi@goffi.org>
parents:
3378
diff
changeset
|
1234 return self.host.disp(msg, verbosity, error, end) |
1605
0aded9648c5c
jp (base): added a self.disp method which manage verbosity and stderr + verbosity property
Goffi <goffi@goffi.org>
parents:
1604
diff
changeset
|
1235 |
1950 | 1236 def output(self, data): |
2193
33b82250eadd
jp (base): raise InternalError if output is used when use_output is not declared
Goffi <goffi@goffi.org>
parents:
2189
diff
changeset
|
1237 try: |
33b82250eadd
jp (base): raise InternalError if output is used when use_output is not declared
Goffi <goffi@goffi.org>
parents:
2189
diff
changeset
|
1238 output_type = self._output_type |
33b82250eadd
jp (base): raise InternalError if output is used when use_output is not declared
Goffi <goffi@goffi.org>
parents:
2189
diff
changeset
|
1239 except AttributeError: |
3040 | 1240 raise exceptions.InternalError( |
1241 _('trying to use output when use_output has not been set')) | |
2193
33b82250eadd
jp (base): raise InternalError if output is used when use_output is not declared
Goffi <goffi@goffi.org>
parents:
2189
diff
changeset
|
1242 return self.host.output(output_type, self.args.output, self.extra_outputs, data) |
1950 | 1243 |
3586
5f65f4e9f8cb
plugin XEP-0060: getItems extra is now serialised dict
Goffi <goffi@goffi.org>
parents:
3568
diff
changeset
|
1244 def getPubsubExtra(self, extra: Optional[dict] = None) -> str: |
2761
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1245 """Helper method to compute extra data from pubsub arguments |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1246 |
3586
5f65f4e9f8cb
plugin XEP-0060: getItems extra is now serialised dict
Goffi <goffi@goffi.org>
parents:
3568
diff
changeset
|
1247 @param extra: base extra dict, or None to generate a new one |
5f65f4e9f8cb
plugin XEP-0060: getItems extra is now serialised dict
Goffi <goffi@goffi.org>
parents:
3568
diff
changeset
|
1248 @return: dict which can be used directly in the bridge for pubsub |
2761
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1249 """ |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1250 if extra is None: |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1251 extra = {} |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1252 else: |
3028 | 1253 intersection = {C.KEY_ORDER_BY}.intersection(list(extra.keys())) |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1254 if intersection: |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1255 raise exceptions.ConflictError( |
3028 | 1256 "given extra dict has conflicting keys with pubsub keys " |
1257 "{intersection}".format(intersection=intersection)) | |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1258 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1259 # RSM |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1260 |
3028 | 1261 for attribute in ('max', 'after', 'before', 'index'): |
1262 key = 'rsm_' + attribute | |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1263 if key in extra: |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1264 raise exceptions.ConflictError( |
3028 | 1265 "This key already exists in extra: u{key}".format(key=key)) |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1266 value = getattr(self.args, key, None) |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1267 if value is not None: |
3028 | 1268 extra[key] = str(value) |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1269 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1270 # MAM |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1271 |
3028 | 1272 if hasattr(self.args, 'mam_filters'): |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1273 for key, value in self.args.mam_filters: |
3028 | 1274 key = 'filter_' + key |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1275 if key in extra: |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1276 raise exceptions.ConflictError( |
3028 | 1277 "This key already exists in extra: u{key}".format(key=key)) |
2764
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1278 extra[key] = value |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1279 |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1280 # Order-By |
92af49cde255
jp (base): MAM and RSM arguments can now be used for pubsub commands:
Goffi <goffi@goffi.org>
parents:
2761
diff
changeset
|
1281 |
2761
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1282 try: |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1283 order_by = self.args.order_by |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1284 except AttributeError: |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1285 pass |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1286 else: |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1287 if order_by is not None: |
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1288 extra[C.KEY_ORDER_BY] = self.args.order_by |
3600
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1289 |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1290 # Cache |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1291 try: |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1292 use_cache = self.args.use_cache |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1293 except AttributeError: |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1294 pass |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1295 else: |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1296 if not use_cache: |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1297 extra[C.KEY_USE_CACHE] = use_cache |
1709f0a78f50
jp (base): add flag for `use_pubsub` to add cache skipping option
Goffi <goffi@goffi.org>
parents:
3586
diff
changeset
|
1298 |
3586
5f65f4e9f8cb
plugin XEP-0060: getItems extra is now serialised dict
Goffi <goffi@goffi.org>
parents:
3568
diff
changeset
|
1299 return data_format.serialise(extra) |
2761
4b693ea24d5f
jp (base, pubsub, ticket): handle order-by:
Goffi <goffi@goffi.org>
parents:
2706
diff
changeset
|
1300 |
817 | 1301 def add_parser_options(self): |
1302 try: | |
1303 subcommands = self.subcommands | |
1304 except AttributeError: | |
1305 # We don't have subcommands, the class need to implements add_parser_options | |
1306 raise NotImplementedError | |
1307 | |
1308 # now we add subcommands to ourself | |
1309 for cls in subcommands: | |
1310 cls(self) | |
814 | 1311 |
3040 | 1312 async def run(self): |
1862
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1313 """this method is called when a command is actually run |
1395
1ae9aa94c351
jp: fixed bad try/except hidding errors + fixed bad management of jids without node
Goffi <goffi@goffi.org>
parents:
1290
diff
changeset
|
1314 |
1862
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1315 It set stuff like progression callbacks and profile connection |
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1316 You should not overide this method: you should call self.start instead |
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1317 """ |
2155 | 1318 # we keep a reference to run command, it may be useful e.g. for outputs |
1319 self.host.command = self | |
1863
b2ddd7f5dcdf
jp (base): refactored need_loop so it is set only when the command is run. It can now be set in __init__ methods of commands classes
Goffi <goffi@goffi.org>
parents:
1862
diff
changeset
|
1320 |
817 | 1321 try: |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1322 show_progress = self.args.progress |
817 | 1323 except AttributeError: |
1324 # the command doesn't use progress bar | |
1325 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
|
1326 else: |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1327 if show_progress: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1328 self.host.watch_progress = True |
3040 | 1329 # we need to register the following signal even if we don't display the |
1330 # progress bar | |
1331 self.host.bridge.register_signal( | |
1332 "progressStarted", self.progressStartedHandler) | |
1333 self.host.bridge.register_signal( | |
1334 "progressFinished", self.progressFinishedHandler) | |
1335 self.host.bridge.register_signal( | |
1336 "progressError", self.progressErrorHandler) | |
817 | 1337 |
1862
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1338 if self.need_connect is not None: |
3040 | 1339 await self.host.connect_profile() |
1340 await self.start() | |
1862
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1341 |
3040 | 1342 async def start(self): |
1343 """This is the starting point of the command, this method must be overriden | |
1862
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1344 |
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1345 at this point, profile are connected if needed |
6d9c87bdc452
jp (base): added a CommandBase.start method which is called by run or connected, so subclasses can implement it (this is for simplicity sake, as it's not always clear if run or connected must be used)
Goffi <goffi@goffi.org>
parents:
1860
diff
changeset
|
1346 """ |
3040 | 1347 raise NotImplementedError |
817 | 1348 |
1349 | |
1350 class CommandAnswering(CommandBase): | |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1351 """Specialised commands which answer to specific actions |
817 | 1352 |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1353 to manage action_types answer, |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1354 """ |
2409
d2ff5ff3de77
jp (ad-hoc): new "list" and "run" commands:
Goffi <goffi@goffi.org>
parents:
2368
diff
changeset
|
1355 action_callbacks = {} # XXX: set managed action types in a dict here: |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1356 # key is the action_type, value is the callable |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1357 # which will manage the answer. profile filtering is |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1358 # already managed when callback is called |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1359 |
2486
031aa3cc67ac
jp (base): fixed assertion error when using CommandAnswering
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
1360 def __init__(self, *args, **kwargs): |
031aa3cc67ac
jp (base): fixed assertion error when using CommandAnswering
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
1361 super(CommandAnswering, self).__init__(*args, **kwargs) |
031aa3cc67ac
jp (base): fixed assertion error when using CommandAnswering
Goffi <goffi@goffi.org>
parents:
2483
diff
changeset
|
1362 |
3040 | 1363 async def onActionNew(self, action_data, action_id, security_limit, profile): |
538
2c4016921403
core, frontends, bridgen plugins: fixed methods which were unproperly managing multi-profiles
Goffi <goffi@goffi.org>
parents:
493
diff
changeset
|
1364 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
|
1365 return |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1366 try: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1367 action_type = action_data['meta_type'] |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1368 except KeyError: |
1840
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1369 try: |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1370 xml_ui = action_data["xmlui"] |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1371 except KeyError: |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1372 pass |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1373 else: |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1374 self.onXMLUI(xml_ui) |
1606
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1375 else: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1376 try: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1377 callback = self.action_callbacks[action_type] |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1378 except KeyError: |
de785fcf9a7b
jp (base, file): file command and progress fixes and adaptation to new API:
Goffi <goffi@goffi.org>
parents:
1605
diff
changeset
|
1379 pass |
0 | 1380 else: |
3040 | 1381 await callback(action_data, action_id, security_limit, profile) |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
1382 |
1840
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1383 def onXMLUI(self, xml_ui): |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1384 """Display a dialog received from the backend. |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1385 |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1386 @param xml_ui (unicode): dialog XML representation |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1387 """ |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1388 # FIXME: we temporarily use ElementTree, but a real XMLUI managing module |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1389 # should be available in the future |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1390 # TODO: XMLUI module |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1391 ui = ET.fromstring(xml_ui.encode('utf-8')) |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1392 dialog = ui.find("dialog") |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1393 if dialog is not None: |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1394 self.disp(dialog.findtext("message"), error=dialog.get("level") == "error") |
9eabf7fadfdd
frontends (jp): onActionNew displays xmlui message if no meta_type is defined and xmlui is defined
souliane <souliane@mailoo.org>
parents:
1832
diff
changeset
|
1395 |
3040 | 1396 async def start_answering(self): |
1397 """Auto reply to confirmation requests""" | |
2368
3865a772c360
jp (base): fixed CommandAnswering and progress bar
Goffi <goffi@goffi.org>
parents:
2313
diff
changeset
|
1398 self.host.bridge.register_signal("actionNew", self.onActionNew) |
3040 | 1399 actions = await self.host.bridge.actionsGet(self.profile) |
1623 | 1400 for action_data, action_id, security_limit in actions: |
3040 | 1401 await self.onActionNew(action_data, action_id, security_limit, self.profile) |