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 )