195 |
195 |
196 import sys |
196 import sys |
197 from os.path import join, dirname, realpath |
197 from os.path import join, dirname, realpath |
198 from warnings import warn |
198 from warnings import warn |
199 from datetime import datetime, date, time, timedelta |
199 from datetime import datetime, date, time, timedelta |
|
200 from functools import partial |
200 |
201 |
201 from logilab.common.decorators import cached, clear_cache |
202 from logilab.common.decorators import cached, clear_cache |
202 from logilab.common.deprecation import deprecated, class_deprecated |
203 from logilab.common.deprecation import deprecated, class_deprecated |
203 from logilab.common.modutils import cleanup_sys_modules |
204 from logilab.common.modutils import cleanup_sys_modules |
204 from logilab.common.registry import ( |
205 from logilab.common.registry import ( |
205 RegistryStore, Registry, classid, |
206 RegistryStore, Registry, obj_registries, |
206 ObjectNotFound, NoSelectableObject, RegistryNotFound) |
207 ObjectNotFound, NoSelectableObject, RegistryNotFound) |
207 |
208 |
208 from rql import RQLHelper |
209 from rql import RQLHelper |
209 from yams.constraints import BASE_CONVERTERS |
210 from yams.constraints import BASE_CONVERTERS |
210 |
211 |
211 from cubicweb import (CW_SOFTWARE_ROOT, ETYPE_NAME_MAP, CW_EVENT_MANAGER, |
212 from cubicweb import (CW_SOFTWARE_ROOT, ETYPE_NAME_MAP, CW_EVENT_MANAGER, |
212 Binary, UnknownProperty, UnknownEid) |
213 Binary, UnknownProperty, UnknownEid) |
213 from cubicweb.rtags import RTAGS |
|
214 from cubicweb.predicates import (implements, appobject_selectable, |
214 from cubicweb.predicates import (implements, appobject_selectable, |
215 _reset_is_instance_cache) |
215 _reset_is_instance_cache) |
216 |
216 |
217 def clear_rtag_objects(): |
217 # backward compat: those modules are now refering to app objects in |
218 for rtag in RTAGS: |
218 # cw.web.views.uicfg and import * from backward compat. On registry reload, we |
219 rtag.clear() |
219 # should pop those modules from the cache so references are properly updated on |
|
220 # subsequent reload |
|
221 CW_EVENT_MANAGER.bind('before-registry-reload', partial(sys.modules.pop, 'cubicweb.web.uicfg', None)) |
|
222 CW_EVENT_MANAGER.bind('before-registry-reload', partial(sys.modules.pop, 'cubicweb.web.uihelper', None)) |
220 |
223 |
221 def use_interfaces(obj): |
224 def use_interfaces(obj): |
222 """return interfaces required by the given object by searching for |
225 """return interfaces required by the given object by searching for |
223 `implements` predicate |
226 `implements` predicate |
224 """ |
227 """ |
259 def related_appobject(obj, appobjectattr='__appobject__'): |
262 def related_appobject(obj, appobjectattr='__appobject__'): |
260 """ adapts any object to a potential appobject bound to it |
263 """ adapts any object to a potential appobject bound to it |
261 through the __appobject__ attribute |
264 through the __appobject__ attribute |
262 """ |
265 """ |
263 return getattr(obj, appobjectattr, obj) |
266 return getattr(obj, appobjectattr, obj) |
|
267 |
|
268 |
|
269 class InstancesRegistry(CWRegistry): |
|
270 |
|
271 def selected(self, winner, args, kwargs): |
|
272 """overriden to avoid the default 'instanciation' behaviour, ie |
|
273 winner(*args, **kwargs) |
|
274 """ |
|
275 return winner |
264 |
276 |
265 |
277 |
266 class ETypeRegistry(CWRegistry): |
278 class ETypeRegistry(CWRegistry): |
267 |
279 |
268 def clear_caches(self): |
280 def clear_caches(self): |
495 REGISTRY_FACTORY = {None: CWRegistry, |
507 REGISTRY_FACTORY = {None: CWRegistry, |
496 'etypes': ETypeRegistry, |
508 'etypes': ETypeRegistry, |
497 'views': ViewsRegistry, |
509 'views': ViewsRegistry, |
498 'actions': ActionsRegistry, |
510 'actions': ActionsRegistry, |
499 'ctxcomponents': CtxComponentsRegistry, |
511 'ctxcomponents': CtxComponentsRegistry, |
|
512 'uicfg': InstancesRegistry, |
500 } |
513 } |
501 |
514 |
502 def __init__(self, config, initlog=True): |
515 def __init__(self, config, initlog=True): |
503 if initlog: |
516 if initlog: |
504 # first init log service |
517 # first init log service |
515 sys.path.remove(webdir) |
528 sys.path.remove(webdir) |
516 if CW_SOFTWARE_ROOT in sys.path: |
529 if CW_SOFTWARE_ROOT in sys.path: |
517 sys.path.remove(CW_SOFTWARE_ROOT) |
530 sys.path.remove(CW_SOFTWARE_ROOT) |
518 self.schema = None |
531 self.schema = None |
519 self.initialized = False |
532 self.initialized = False |
520 # XXX give force_reload (or refactor [re]loading...) |
|
521 if self.config.mode != 'test': |
|
522 # don't clear rtags during test, this may cause breakage with |
|
523 # manually imported appobject modules |
|
524 CW_EVENT_MANAGER.bind('before-registry-reload', clear_rtag_objects) |
|
525 self['boxes'] = BwCompatCWRegistry(self, 'boxes', 'ctxcomponents') |
533 self['boxes'] = BwCompatCWRegistry(self, 'boxes', 'ctxcomponents') |
526 self['contentnavigation'] = BwCompatCWRegistry(self, 'contentnavigation', 'ctxcomponents') |
534 self['contentnavigation'] = BwCompatCWRegistry(self, 'contentnavigation', 'ctxcomponents') |
527 |
535 |
528 def setdefault(self, regid): |
536 def setdefault(self, regid): |
529 try: |
537 try: |
693 and iface in self.schema |
701 and iface in self.schema |
694 and self['etypes'].etype_class(iface) |
702 and self['etypes'].etype_class(iface) |
695 or iface |
703 or iface |
696 for iface in ifaces) |
704 for iface in ifaces) |
697 if not ('Any' in ifaces or ifaces & implemented_interfaces): |
705 if not ('Any' in ifaces or ifaces & implemented_interfaces): |
|
706 reg = self[obj_registries(obj)[0]] |
698 self.debug('unregister %s (no implemented ' |
707 self.debug('unregister %s (no implemented ' |
699 'interface among %s)', classid(obj), ifaces) |
708 'interface among %s)', reg.objid(obj), ifaces) |
700 self.unregister(obj) |
709 self.unregister(obj) |
701 # since 3.9: remove appobjects which depending on other, unexistant |
710 # since 3.9: remove appobjects which depending on other, unexistant |
702 # appobjects |
711 # appobjects |
703 for obj, (regname, regids) in self._needs_appobject.items(): |
712 for obj, (regname, regids) in self._needs_appobject.items(): |
704 try: |
713 try: |
705 registry = self[regname] |
714 registry = self[regname] |
706 except RegistryNotFound: |
715 except RegistryNotFound: |
707 self.debug('unregister %s (no registry %s)', classid(obj), |
716 self.debug('unregister %s (no registry %s)', obj, regname) |
708 regname) |
|
709 self.unregister(obj) |
717 self.unregister(obj) |
710 continue |
718 continue |
711 for regid in regids: |
719 for regid in regids: |
712 if registry.get(regid): |
720 if registry.get(regid): |
713 break |
721 break |
714 else: |
722 else: |
715 self.debug('unregister %s (no %s object in registry %s)', |
723 self.debug('unregister %s (no %s object in registry %s)', |
716 classid(obj), ' or '.join(regids), regname) |
724 registry.objid(obj), ' or '.join(regids), regname) |
717 self.unregister(obj) |
725 self.unregister(obj) |
718 super(CWRegistryStore, self).initialization_completed() |
726 super(CWRegistryStore, self).initialization_completed() |
719 for rtag in RTAGS: |
727 if 'uicfg' in self: # 'uicfg' is not loaded in a pure repository mode |
720 # don't check rtags if we don't want to cleanup_interface_sobjects |
728 for rtags in self['uicfg'].values(): |
721 rtag.init(self.schema, check=self.config.cleanup_interface_sobjects) |
729 for rtag in rtags: |
|
730 # don't check rtags if we don't want to cleanup_interface_sobjects |
|
731 rtag.init(self.schema, check=self.config.cleanup_interface_sobjects) |
722 |
732 |
723 # rql parsing utilities #################################################### |
733 # rql parsing utilities #################################################### |
724 |
734 |
725 @property |
735 @property |
726 @cached |
736 @cached |