Mercurial > libervia-backend
comparison sat_frontends/quick_frontend/quick_widgets.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | 003b8b4b56a7 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
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 from sat.core.log import getLogger | 20 from sat.core.log import getLogger |
21 | |
21 log = getLogger(__name__) | 22 log = getLogger(__name__) |
22 from sat.core import exceptions | 23 from sat.core import exceptions |
23 from sat_frontends.quick_frontend.constants import Const as C | 24 from sat_frontends.quick_frontend.constants import Const as C |
24 | 25 |
25 | 26 |
26 NEW_INSTANCE_SUFF = '_new_instance_' | 27 NEW_INSTANCE_SUFF = "_new_instance_" |
27 classes_map = {} | 28 classes_map = {} |
28 | 29 |
29 | 30 |
30 try: | 31 try: |
31 # FIXME: to be removed when an acceptable solution is here | 32 # FIXME: to be removed when an acceptable solution is here |
32 unicode('') # XXX: unicode doesn't exist in pyjamas | 33 unicode("") # XXX: unicode doesn't exist in pyjamas |
33 except (TypeError, AttributeError): # Error raised is not the same depending on pyjsbuild options | 34 except ( |
35 TypeError, | |
36 AttributeError, | |
37 ): # Error raised is not the same depending on pyjsbuild options | |
34 unicode = str | 38 unicode = str |
35 | 39 |
36 | 40 |
37 def register(base_cls, child_cls=None): | 41 def register(base_cls, child_cls=None): |
38 """Register a child class to use by default when a base class is needed | 42 """Register a child class to use by default when a base class is needed |
75 # in the second case | 79 # in the second case |
76 cls = classes_map[class_.__name__] | 80 cls = classes_map[class_.__name__] |
77 except KeyError: | 81 except KeyError: |
78 cls = class_ | 82 cls = class_ |
79 if cls is None: | 83 if cls is None: |
80 raise exceptions.InternalError("There is not class registered for {}".format(class_)) | 84 raise exceptions.InternalError( |
85 "There is not class registered for {}".format(class_) | |
86 ) | |
81 return cls | 87 return cls |
82 | 88 |
83 def getRootHash(self, hash_): | 89 def getRootHash(self, hash_): |
84 """Return root hash (i.e. hash without new instance suffix for recreated widgets | 90 """Return root hash (i.e. hash without new instance suffix for recreated widgets |
85 | 91 |
107 filter_hash = unicode(class_.getWidgetHash(target, profiles)) | 113 filter_hash = unicode(class_.getWidgetHash(target, profiles)) |
108 else: | 114 else: |
109 filter_hash = None | 115 filter_hash = None |
110 for w_hash, w in widgets_map.iteritems(): | 116 for w_hash, w in widgets_map.iteritems(): |
111 if profiles is None or w.profiles.intersection(profiles): | 117 if profiles is None or w.profiles.intersection(profiles): |
112 if filter_hash is not None and self.getRootHash(w_hash) != filter_hash: | 118 if ( |
119 filter_hash is not None | |
120 and self.getRootHash(w_hash) != filter_hash | |
121 ): | |
113 continue | 122 continue |
114 yield w | 123 yield w |
115 | 124 |
116 def getWidget(self, class_, target=None, profiles=None): | 125 def getWidget(self, class_, target=None, profiles=None): |
117 """Get a widget without creating it if it doesn't exist. | 126 """Get a widget without creating it if it doesn't exist. |
159 @return: a class_ instance, either new or already existing | 168 @return: a class_ instance, either new or already existing |
160 """ | 169 """ |
161 cls = self.getRealClass(class_) | 170 cls = self.getRealClass(class_) |
162 | 171 |
163 ## arguments management ## | 172 ## arguments management ## |
164 _args = [self.host, target] + list(args) or [] # FIXME: check if it's really necessary to use optional args | 173 _args = [self.host, target] + list( |
174 args | |
175 ) or [] # FIXME: check if it's really necessary to use optional args | |
165 _kwargs = kwargs or {} | 176 _kwargs = kwargs or {} |
166 if 'profiles' in _kwargs and 'profile' in _kwargs: | 177 if "profiles" in _kwargs and "profile" in _kwargs: |
167 raise ValueError("You can't have 'profile' and 'profiles' keys at the same time") | 178 raise ValueError( |
168 try: | 179 "You can't have 'profile' and 'profiles' keys at the same time" |
169 _kwargs['profiles'] = [_kwargs.pop('profile')] | 180 ) |
170 except KeyError: | 181 try: |
171 if not 'profiles' in _kwargs: | 182 _kwargs["profiles"] = [_kwargs.pop("profile")] |
172 _kwargs['profiles'] = None | 183 except KeyError: |
173 | 184 if not "profiles" in _kwargs: |
174 #on_new_widget tell what to do for the new widget creation | 185 _kwargs["profiles"] = None |
175 try: | 186 |
176 on_new_widget = _kwargs.pop('on_new_widget') | 187 # on_new_widget tell what to do for the new widget creation |
188 try: | |
189 on_new_widget = _kwargs.pop("on_new_widget") | |
177 except KeyError: | 190 except KeyError: |
178 on_new_widget = C.WIDGET_NEW | 191 on_new_widget = C.WIDGET_NEW |
179 | 192 |
180 #on_existing_widget tell what to do when the widget already exists | 193 # on_existing_widget tell what to do when the widget already exists |
181 try: | 194 try: |
182 on_existing_widget = _kwargs.pop('on_existing_widget') | 195 on_existing_widget = _kwargs.pop("on_existing_widget") |
183 except KeyError: | 196 except KeyError: |
184 on_existing_widget = C.WIDGET_KEEP | 197 on_existing_widget = C.WIDGET_KEEP |
185 | 198 |
186 ## we get the hash ## | 199 ## we get the hash ## |
187 try: | 200 try: |
188 hash_ = _kwargs.pop('force_hash') | 201 hash_ = _kwargs.pop("force_hash") |
189 except KeyError: | 202 except KeyError: |
190 hash_ = cls.getWidgetHash(target, _kwargs['profiles']) | 203 hash_ = cls.getWidgetHash(target, _kwargs["profiles"]) |
191 | 204 |
192 ## widget creation or retrieval ## | 205 ## widget creation or retrieval ## |
193 | 206 |
194 widgets_map = self._widgets.setdefault(cls.__name__, {}) # we sorts widgets by classes | 207 widgets_map = self._widgets.setdefault( |
208 cls.__name__, {} | |
209 ) # we sorts widgets by classes | |
195 if not cls.SINGLE: | 210 if not cls.SINGLE: |
196 widget = None # if the class is not SINGLE, we always create a new widget | 211 widget = None # if the class is not SINGLE, we always create a new widget |
197 else: | 212 else: |
198 try: | 213 try: |
199 widget = widgets_map[hash_] | 214 widget = widgets_map[hash_] |
200 widget.addTarget(target) | 215 widget.addTarget(target) |
201 except KeyError: | 216 except KeyError: |
223 # we use getOrCreateWidget to recreate the new widget | 238 # we use getOrCreateWidget to recreate the new widget |
224 # /!\ we use args and kwargs and not _args and _kwargs because we need the original args | 239 # /!\ we use args and kwargs and not _args and _kwargs because we need the original args |
225 # we need to get rid of kwargs special options | 240 # we need to get rid of kwargs special options |
226 new_kwargs = kwargs.copy() | 241 new_kwargs = kwargs.copy() |
227 try: | 242 try: |
228 new_kwargs.pop('force_hash') # FIXME: we use pop instead of del here because pyjamas doesn't raise error on del | 243 new_kwargs.pop( |
244 "force_hash" | |
245 ) # FIXME: we use pop instead of del here because pyjamas doesn't raise error on del | |
229 except KeyError: | 246 except KeyError: |
230 pass | 247 pass |
231 else: | 248 else: |
232 raise ValueError("force_hash option can't be used with on_existing_widget=RECREATE") | 249 raise ValueError( |
233 | 250 "force_hash option can't be used with on_existing_widget=RECREATE" |
234 new_kwargs['on_new_widget'] = on_new_widget | 251 ) |
252 | |
253 new_kwargs["on_new_widget"] = on_new_widget | |
235 | 254 |
236 # XXX: keep up-to-date if new special kwargs are added (i.e.: delete these keys here) | 255 # XXX: keep up-to-date if new special kwargs are added (i.e.: delete these keys here) |
237 new_kwargs['on_existing_widget'] = C.WIDGET_RAISE | 256 new_kwargs["on_existing_widget"] = C.WIDGET_RAISE |
238 try: | 257 try: |
239 recreateArgs = widget.recreateArgs | 258 recreateArgs = widget.recreateArgs |
240 except AttributeError: | 259 except AttributeError: |
241 pass | 260 pass |
242 else: | 261 else: |
243 recreateArgs(args, new_kwargs) | 262 recreateArgs(args, new_kwargs) |
244 hash_idx = 1 | 263 hash_idx = 1 |
245 while True: | 264 while True: |
246 new_kwargs['force_hash'] = "{}{}{}".format(hash_, NEW_INSTANCE_SUFF, hash_idx) | 265 new_kwargs["force_hash"] = "{}{}{}".format( |
266 hash_, NEW_INSTANCE_SUFF, hash_idx | |
267 ) | |
247 try: | 268 try: |
248 widget = self.getOrCreateWidget(class_, target, *args, **new_kwargs) | 269 widget = self.getOrCreateWidget( |
270 class_, target, *args, **new_kwargs | |
271 ) | |
249 except WidgetAlreadyExistsError: | 272 except WidgetAlreadyExistsError: |
250 hash_idx += 1 | 273 hash_idx += 1 |
251 else: | 274 else: |
252 log.debug(u"Widget already exists, a new one has been recreated with hash {}".format(new_kwargs['force_hash'])) | 275 log.debug( |
276 u"Widget already exists, a new one has been recreated with hash {}".format( | |
277 new_kwargs["force_hash"] | |
278 ) | |
279 ) | |
253 break | 280 break |
254 elif callable(on_existing_widget): | 281 elif callable(on_existing_widget): |
255 on_existing_widget(widget) | 282 on_existing_widget(widget) |
256 else: | 283 else: |
257 raise exceptions.InternalError("Unexpected on_existing_widget value ({})".format(on_existing_widget)) | 284 raise exceptions.InternalError( |
285 "Unexpected on_existing_widget value ({})".format(on_existing_widget) | |
286 ) | |
258 | 287 |
259 return widget | 288 return widget |
260 | 289 |
261 def deleteWidget(self, widget_to_delete, *args, **kwargs): | 290 def deleteWidget(self, widget_to_delete, *args, **kwargs): |
262 """Delete a widget | 291 """Delete a widget |
284 del widget_map[hash_] | 313 del widget_map[hash_] |
285 | 314 |
286 | 315 |
287 class QuickWidget(object): | 316 class QuickWidget(object): |
288 """generic widget base""" | 317 """generic widget base""" |
289 SINGLE=True # if True, there can be only one widget per target(s) | 318 |
290 PROFILES_MULTIPLE=False # If True, this widget can handle several profiles at once | 319 SINGLE = True # if True, there can be only one widget per target(s) |
291 PROFILES_ALLOW_NONE=False # If True, this widget can be used without profile | 320 PROFILES_MULTIPLE = False # If True, this widget can handle several profiles at once |
321 PROFILES_ALLOW_NONE = False # If True, this widget can be used without profile | |
292 | 322 |
293 def __init__(self, host, target, profiles=None): | 323 def __init__(self, host, target, profiles=None): |
294 """ | 324 """ |
295 @param host: %(doc_host)s | 325 @param host: %(doc_host)s |
296 @param target: target specific for this widget class | 326 @param target: target specific for this widget class |
315 if not self.profiles: | 345 if not self.profiles: |
316 raise ValueError("no profile found, use None for no profile classes") | 346 raise ValueError("no profile found, use None for no profile classes") |
317 | 347 |
318 @property | 348 @property |
319 def profile(self): | 349 def profile(self): |
320 assert len(self.profiles) == 1 and not self.PROFILES_MULTIPLE and not self.PROFILES_ALLOW_NONE | 350 assert ( |
351 len(self.profiles) == 1 | |
352 and not self.PROFILES_MULTIPLE | |
353 and not self.PROFILES_ALLOW_NONE | |
354 ) | |
321 return list(self.profiles)[0] | 355 return list(self.profiles)[0] |
322 | 356 |
323 def addTarget(self, target): | 357 def addTarget(self, target): |
324 """Add a target if it doesn't already exists | 358 """Add a target if it doesn't already exists |
325 | 359 |
348 | 382 |
349 @param target: target to check | 383 @param target: target to check |
350 @param profiles: profile(s) associated to target, see __init__ docstring | 384 @param profiles: profile(s) associated to target, see __init__ docstring |
351 @return: a hash (can correspond to one or many targets or profiles, depending of widget class) | 385 @return: a hash (can correspond to one or many targets or profiles, depending of widget class) |
352 """ | 386 """ |
353 return unicode(target) # by defaut, there is one hash for one target | 387 return unicode(target) # by defaut, there is one hash for one target |
354 | 388 |
355 def onDelete(self, *args, **kwargs): | 389 def onDelete(self, *args, **kwargs): |
356 """Called when a widget is being deleted | 390 """Called when a widget is being deleted |
357 | 391 |
358 @return (boot, None): False to cancel deletion | 392 @return (boot, None): False to cancel deletion |
359 all other value continue deletion | 393 all other value continue deletion |
360 """ | 394 """ |
361 log.debug(u"widget {} deleted".format(self)) | 395 log.debug(u"widget {} deleted".format(self)) |
362 return True | 396 return True |
363 |