Mercurial > libervia-backend
comparison sat_frontends/jp/cmd_avatar.py @ 3040:fee60f17ebac
jp: jp asyncio port:
/!\ this commit is huge. Jp is temporarily not working with `dbus` bridge /!\
This patch implements the port of jp to asyncio, so it is now correctly using the bridge
asynchronously, and it can be used with bridges like `pb`. This also simplify the code,
notably for things which were previously implemented with many callbacks (like pagination
with RSM).
During the process, some behaviours have been modified/fixed, in jp and backends, check
diff for details.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 25 Sep 2019 08:56:41 +0200 |
parents | ab2696e34d29 |
children | 9d0df638c8b4 |
comparison
equal
deleted
inserted
replaced
3039:a1bc34f90fa5 | 3040:fee60f17ebac |
---|---|
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 | 20 |
21 from . import base | |
22 import os | 21 import os |
23 import os.path | 22 import os.path |
23 import asyncio | |
24 from . import base | |
24 from sat.core.i18n import _ | 25 from sat.core.i18n import _ |
25 from sat_frontends.jp.constants import Const as C | 26 from sat_frontends.jp.constants import Const as C |
26 from sat.tools import config | 27 from sat.tools import config |
27 import subprocess | |
28 | 28 |
29 | 29 |
30 __commands__ = ["Avatar"] | 30 __commands__ = ["Avatar"] |
31 DISPLAY_CMD = ["xv", "display", "gwenview", "showtell"] | 31 DISPLAY_CMD = ["xv", "display", "gwenview", "showtell"] |
32 | |
33 | |
34 class Get(base.CommandBase): | |
35 def __init__(self, host): | |
36 super(Get, self).__init__( | |
37 host, "get", use_verbose=True, help=_("retrieve avatar of an entity") | |
38 ) | |
39 | |
40 def add_parser_options(self): | |
41 self.parser.add_argument("jid", help=_("entity")) | |
42 self.parser.add_argument( | |
43 "-s", "--show", action="store_true", help=_("show avatar") | |
44 ) | |
45 | |
46 async def showImage(self, path): | |
47 sat_conf = config.parseMainConf() | |
48 cmd = config.getConfig(sat_conf, "jp", "image_cmd") | |
49 cmds = [cmd] + DISPLAY_CMD if cmd else DISPLAY_CMD | |
50 for cmd in cmds: | |
51 try: | |
52 process = await asyncio.create_subprocess_exec(cmd, path) | |
53 ret = await process.wait() | |
54 except OSError: | |
55 continue | |
56 | |
57 if ret in (0, 2): | |
58 # we can get exit code 2 with display when stopping it with C-c | |
59 break | |
60 else: | |
61 # didn't worked with commands, we try our luck with webbrowser | |
62 # in some cases, webbrowser can actually open the associated display program. | |
63 # Note that this may be possibly blocking, depending on the platform and | |
64 # available browser | |
65 import webbrowser | |
66 | |
67 webbrowser.open(path) | |
68 | |
69 async def start(self): | |
70 try: | |
71 avatar_path = await self.host.bridge.avatarGet( | |
72 self.args.jid, | |
73 False, | |
74 False, | |
75 self.profile, | |
76 ) | |
77 except Exception as e: | |
78 self.disp(f"can't retrieve avatar: {e}", error=True) | |
79 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
80 | |
81 if not avatar_path: | |
82 self.disp(_("No avatar found."), 1) | |
83 self.host.quit(C.EXIT_NOT_FOUND) | |
84 | |
85 self.disp(avatar_path) | |
86 if self.args.show: | |
87 await self.showImage(avatar_path) | |
88 | |
89 self.host.quit() | |
32 | 90 |
33 | 91 |
34 class Set(base.CommandBase): | 92 class Set(base.CommandBase): |
35 def __init__(self, host): | 93 def __init__(self, host): |
36 super(Set, self).__init__( | 94 super(Set, self).__init__( |
37 host, "set", use_verbose=True, help=_("set avatar of the profile") | 95 host, "set", use_verbose=True, help=_("set avatar of the profile") |
38 ) | 96 ) |
39 self.need_loop = True | |
40 | 97 |
41 def add_parser_options(self): | 98 def add_parser_options(self): |
42 self.parser.add_argument( | 99 self.parser.add_argument( |
43 "image_path", type=str, help=_("path to the image to upload") | 100 "image_path", type=str, help=_("path to the image to upload") |
44 ) | 101 ) |
45 | 102 |
46 def start(self): | 103 async def start(self): |
47 """Send files to jabber contact""" | |
48 path = self.args.image_path | 104 path = self.args.image_path |
49 if not os.path.exists(path): | 105 if not os.path.exists(path): |
50 self.disp(_("file [{}] doesn't exist !").format(path), error=True) | 106 self.disp(_(f"file {path!r} doesn't exist!"), error=True) |
51 self.host.quit(1) | 107 self.host.quit(C.EXIT_BAD_ARG) |
52 path = os.path.abspath(path) | 108 path = os.path.abspath(path) |
53 self.host.bridge.avatarSet( | 109 try: |
54 path, self.profile, callback=self._avatarCb, errback=self._avatarEb | 110 await self.host.bridge.avatarSet(path, self.profile) |
55 ) | 111 except Exception as e: |
56 | 112 self.disp(f"can't set avatar: {e}", error=True) |
57 def _avatarCb(self): | 113 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
58 self.disp(_("avatar has been set"), 1) | |
59 self.host.quit() | |
60 | |
61 def _avatarEb(self, failure_): | |
62 self.disp( | |
63 _("error while uploading avatar: {msg}").format(msg=failure_), error=True | |
64 ) | |
65 self.host.quit(C.EXIT_ERROR) | |
66 | |
67 | |
68 class Get(base.CommandBase): | |
69 def __init__(self, host): | |
70 super(Get, self).__init__( | |
71 host, "get", use_verbose=True, help=_("retrieve avatar of an entity") | |
72 ) | |
73 self.need_loop = True | |
74 | |
75 def add_parser_options(self): | |
76 self.parser.add_argument("jid", help=_("entity")) | |
77 self.parser.add_argument( | |
78 "-s", "--show", action="store_true", help=_("show avatar") | |
79 ) | |
80 | |
81 def showImage(self, path): | |
82 sat_conf = config.parseMainConf() | |
83 cmd = config.getConfig(sat_conf, "jp", "image_cmd") | |
84 cmds = [cmd] + DISPLAY_CMD if cmd else DISPLAY_CMD | |
85 for cmd in cmds: | |
86 try: | |
87 ret = subprocess.call([cmd] + [path]) | |
88 except OSError: | |
89 pass | |
90 else: | |
91 if ret in (0, 2): | |
92 # we can get exit code 2 with display when stopping it with C-c | |
93 break | |
94 else: | 114 else: |
95 # didn't worked with commands, we try our luck with webbrowser | 115 self.disp(_("avatar has been set"), 1) |
96 # in some cases, webbrowser can actually open the associated display program | 116 self.host.quit() |
97 import webbrowser | |
98 | |
99 webbrowser.open(path) | |
100 | |
101 def _avatarGetCb(self, avatar_path): | |
102 if not avatar_path: | |
103 self.disp(_("No avatar found."), 1) | |
104 self.host.quit(C.EXIT_NOT_FOUND) | |
105 | |
106 self.disp(avatar_path) | |
107 if self.args.show: | |
108 self.showImage(avatar_path) | |
109 | |
110 self.host.quit() | |
111 | |
112 def _avatarGetEb(self, failure_): | |
113 self.disp(_("error while getting avatar: {msg}").format(msg=failure_), error=True) | |
114 self.host.quit(C.EXIT_ERROR) | |
115 | |
116 def start(self): | |
117 self.host.bridge.avatarGet( | |
118 self.args.jid, | |
119 False, | |
120 False, | |
121 self.profile, | |
122 callback=self._avatarGetCb, | |
123 errback=self._avatarGetEb, | |
124 ) | |
125 | 117 |
126 | 118 |
127 class Avatar(base.CommandBase): | 119 class Avatar(base.CommandBase): |
128 subcommands = (Set, Get) | 120 subcommands = (Get, Set) |
129 | 121 |
130 def __init__(self, host): | 122 def __init__(self, host): |
131 super(Avatar, self).__init__( | 123 super(Avatar, self).__init__( |
132 host, "avatar", use_profile=False, help=_("avatar uploading/retrieving") | 124 host, "avatar", use_profile=False, help=_("avatar uploading/retrieving") |
133 ) | 125 ) |