author | Adrien Di Mascio <Adrien.DiMascio@logilab.fr> |
Wed, 18 Feb 2009 11:38:05 +0100 | |
branch | tls-sprint |
changeset 769 | 2b49c9932d8c |
parent 725 | 2f3e6afabdb5 |
child 778 | 847db4c91061 |
permissions | -rw-r--r-- |
0 | 1 |
"""This file contains some basic registerers required by application objects |
2 |
registry to handle registration at startup time. |
|
3 |
||
4 |
A registerer is responsible to tell if an object should be registered according |
|
5 |
to the application's schema or to already registered object |
|
6 |
||
7 |
:organization: Logilab |
|
631
99f5852f8604
major selector refactoring (mostly to avoid looking for select parameters on the target class), start accept / interface unification)
sylvain.thenault@logilab.fr
parents:
0
diff
changeset
|
8 |
:copyright: 2006-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
0 | 9 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
10 |
""" |
|
11 |
__docformat__ = "restructuredtext en" |
|
12 |
||
718
f7011679437a
doc update, move yes_registerer here
sylvain.thenault@logilab.fr
parents:
717
diff
changeset
|
13 |
from cubicweb.vregistry import registerer, yes_registerer |
694
520661be60e4
kill kick_registerer (actually moved to asteretud), fix _accepts_interface w/ new implements selector
sylvain.thenault@logilab.fr
parents:
670
diff
changeset
|
14 |
from cubicweb.selectors import implements |
0 | 15 |
|
16 |
def _accepts_interfaces(obj): |
|
725
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
17 |
try: |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
18 |
return sorted(obj.accepts_interfaces) |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
19 |
except AttributeError: |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
20 |
try: |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
21 |
impl = obj.__select__.search_selector(implements) |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
22 |
if impl: |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
23 |
return sorted(impl.expected_ifaces) |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
24 |
except AttributeError: |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
25 |
pass # old-style vobject classes with no accepts_interfaces |
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
26 |
return () |
0 | 27 |
|
28 |
||
29 |
class priority_registerer(registerer): |
|
30 |
"""systematically kick previous registered class and register the |
|
31 |
wrapped class (based on the fact that directory containing vobjects |
|
32 |
are loaded from the most generic to the most specific). |
|
33 |
||
34 |
This is usually for templates or startup views where we want to |
|
35 |
keep only the latest in the load path |
|
36 |
""" |
|
37 |
def do_it_yourself(self, registered): |
|
38 |
if registered: |
|
39 |
if len(registered) > 1: |
|
40 |
self.warning('priority_registerer found more than one registered objects ' |
|
41 |
'(registerer monkey patch ?)') |
|
42 |
for regobj in registered[:]: |
|
43 |
self.kick(registered, regobj) |
|
44 |
return self.vobject |
|
45 |
||
46 |
def remove_equivalents(self, registered): |
|
47 |
for _obj in registered[:]: |
|
48 |
if self.equivalent(_obj): |
|
49 |
self.kick(registered, _obj) |
|
50 |
break |
|
51 |
||
52 |
def remove_all_equivalents(self, registered): |
|
53 |
for _obj in registered[:]: |
|
54 |
if _obj is self.vobject: |
|
55 |
continue |
|
56 |
if self.equivalent(_obj): |
|
57 |
self.kick(registered, _obj) |
|
58 |
||
59 |
def equivalent(self, other): |
|
60 |
raise NotImplementedError(self, self.vobject) |
|
61 |
||
62 |
||
63 |
class accepts_registerer(priority_registerer): |
|
64 |
"""register according to the .accepts attribute of the wrapped |
|
65 |
class, which should be a tuple refering some entity's types |
|
66 |
||
67 |
* if no type is defined the application'schema, skip the wrapped |
|
68 |
class |
|
69 |
* if the class defines a requires attribute, each entity type defined |
|
70 |
in the requires list must be in the schema |
|
71 |
* if an object previously registered has equivalent .accepts |
|
72 |
attribute, kick it out |
|
73 |
* register |
|
74 |
""" |
|
75 |
def do_it_yourself(self, registered): |
|
76 |
# if object is accepting interface, we have register it now and |
|
725
2f3e6afabdb5
safety belt inside _accept_interfaces() as it might be called on a class that doesn't provide (yet) __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
718
diff
changeset
|
77 |
# remove it later if no object is implementing accepted interfaces |
0 | 78 |
if _accepts_interfaces(self.vobject): |
79 |
return self.vobject |
|
80 |
self.remove_equivalents(registered) |
|
81 |
return self.vobject |
|
82 |
||
83 |
def equivalent(self, other): |
|
84 |
if _accepts_interfaces(self.vobject) != _accepts_interfaces(other): |
|
85 |
return False |
|
86 |
try: |
|
87 |
newaccepts = list(other.accepts) |
|
88 |
for etype in self.vobject.accepts: |
|
89 |
try: |
|
90 |
newaccepts.remove(etype) |
|
91 |
except ValueError: |
|
92 |
continue |
|
93 |
if newaccepts: |
|
94 |
other.accepts = tuple(newaccepts) |
|
95 |
return False |
|
96 |
return True |
|
97 |
except AttributeError: |
|
98 |
return False |
|
99 |
||
100 |
||
101 |
__all__ = [cls.__name__ for cls in globals().values() |
|
102 |
if isinstance(cls, type) and issubclass(cls, registerer) |
|
103 |
and not cls is registerer] |