10 from warnings import warn |
10 from warnings import warn |
11 |
11 |
12 from logilab.common import interface |
12 from logilab.common import interface |
13 from logilab.common.compat import all |
13 from logilab.common.compat import all |
14 from logilab.common.decorators import cached |
14 from logilab.common.decorators import cached |
15 from logilab.common.deprecation import deprecated |
|
16 from logilab.mtconverter import TransformData, TransformError, xml_escape |
15 from logilab.mtconverter import TransformData, TransformError, xml_escape |
17 |
16 |
18 from rql.utils import rqlvar_maker |
17 from rql.utils import rqlvar_maker |
19 |
18 |
20 from cubicweb import Unauthorized |
19 from cubicweb import Unauthorized |
21 from cubicweb.rset import ResultSet |
20 from cubicweb.rset import ResultSet |
22 from cubicweb.selectors import yes |
21 from cubicweb.selectors import yes |
23 from cubicweb.appobject import AppObject |
22 from cubicweb.appobject import AppObject |
24 from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint, bw_normalize_etype |
23 from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint |
25 |
24 |
26 from cubicweb.common.uilib import printable_value, soup2xhtml |
25 from cubicweb.common.uilib import printable_value, soup2xhtml |
27 from cubicweb.common.mixins import MI_REL_TRIGGERS |
26 from cubicweb.common.mixins import MI_REL_TRIGGERS |
28 from cubicweb.common.mttransforms import ENGINE |
27 from cubicweb.common.mttransforms import ENGINE |
29 |
28 |
36 if card in '+*': |
35 if card in '+*': |
37 return card |
36 return card |
38 return '1' |
37 return '1' |
39 |
38 |
40 |
39 |
41 _MODE_TAGS = set(('link', 'create')) |
|
42 _CATEGORY_TAGS = set(('primary', 'secondary', 'generic', 'generated')) # , 'metadata')) |
|
43 |
|
44 try: |
|
45 from cubicweb.web import formwidgets, uicfg |
|
46 |
|
47 def _dispatch_rtags(tags, rtype, role, stype, otype): |
|
48 for tag in tags: |
|
49 if tag in _MODE_TAGS: |
|
50 uicfg.actionbox_appearsin_addmenu.tag_relation( |
|
51 (stype, rtype, otype, role), tag == 'create') |
|
52 elif tag in _CATEGORY_TAGS: |
|
53 uicfg.autoform_section.tag_relation((stype, rtype, otype, role), |
|
54 tag) |
|
55 elif tag == 'inlineview': |
|
56 uicfg.autoform_is_inlined.tag_relation((stype, rtype, otype, role), True) |
|
57 else: |
|
58 raise ValueError(tag) |
|
59 |
|
60 except ImportError: |
|
61 |
|
62 _dispatch_rtags = None |
|
63 |
|
64 def _get_etype(bases, classdict): |
|
65 try: |
|
66 return classdict['id'] |
|
67 except KeyError: |
|
68 for base in bases: |
|
69 etype = getattr(base, 'id', None) |
|
70 if etype and etype != 'Any': |
|
71 return etype |
|
72 |
|
73 def _get_defs(attr, name, bases, classdict): |
|
74 try: |
|
75 yield name, classdict.pop(attr) |
|
76 except KeyError: |
|
77 for base in bases: |
|
78 try: |
|
79 value = getattr(base, attr) |
|
80 delattr(base, attr) |
|
81 yield base.__name__, value |
|
82 except AttributeError: |
|
83 continue |
|
84 |
|
85 class _metaentity(type): |
|
86 """this metaclass sets the relation tags on the entity class |
|
87 and deals with the `widgets` attribute |
|
88 """ |
|
89 def __new__(mcs, name, bases, classdict): |
|
90 # collect baseclass' rtags |
|
91 etype = _get_etype(bases, classdict) |
|
92 if etype and _dispatch_rtags is not None: |
|
93 for name, rtags in _get_defs('__rtags__', name, bases, classdict): |
|
94 warn('%s: __rtags__ is deprecated' % name, DeprecationWarning) |
|
95 for relation, tags in rtags.iteritems(): |
|
96 # tags must become an iterable |
|
97 if isinstance(tags, basestring): |
|
98 tags = (tags,) |
|
99 # relation must become a 3-uple (rtype, targettype, role) |
|
100 if isinstance(relation, basestring): |
|
101 _dispatch_rtags(tags, relation, 'subject', etype, '*') |
|
102 _dispatch_rtags(tags, relation, 'object', '*', etype) |
|
103 elif len(relation) == 1: # useful ? |
|
104 _dispatch_rtags(tags, relation[0], 'subject', etype, '*') |
|
105 _dispatch_rtags(tags, relation[0], 'object', '*', etype) |
|
106 elif len(relation) == 2: |
|
107 rtype, ttype = relation |
|
108 ttype = bw_normalize_etype(ttype) # XXX bw compat |
|
109 _dispatch_rtags(tags, rtype, 'subject', etype, ttype) |
|
110 _dispatch_rtags(tags, rtype, 'object', ttype, etype) |
|
111 elif len(relation) == 3: |
|
112 rtype, ttype, role = relation |
|
113 ttype = bw_normalize_etype(ttype) |
|
114 if role == 'subject': |
|
115 _dispatch_rtags(tags, rtype, 'subject', etype, ttype) |
|
116 else: |
|
117 _dispatch_rtags(tags, rtype, 'object', ttype, etype) |
|
118 else: |
|
119 raise ValueError('bad rtag definition (%r)' % (relation,)) |
|
120 for name, widgets in _get_defs('widgets', name, bases, classdict): |
|
121 warn('%s: widgets is deprecated' % name, DeprecationWarning) |
|
122 for rtype, wdgname in widgets.iteritems(): |
|
123 if wdgname in ('URLWidget', 'EmbededURLWidget', 'RawDynamicComboBoxWidget'): |
|
124 warn('%s widget is deprecated' % wdgname, DeprecationWarning) |
|
125 continue |
|
126 if wdgname == 'StringWidget': |
|
127 wdgname = 'TextInput' |
|
128 widget = getattr(formwidgets, wdgname) |
|
129 assert hasattr(widget, 'render') |
|
130 uicfg.autoform_field_kwargs.tag_subject_of( |
|
131 (etype, rtype, '*'), {'widget': widget}) |
|
132 return super(_metaentity, mcs).__new__(mcs, name, bases, classdict) |
|
133 |
|
134 |
|
135 class Entity(AppObject, dict): |
40 class Entity(AppObject, dict): |
136 """an entity instance has e_schema automagically set on |
41 """an entity instance has e_schema automagically set on |
137 the class and instances has access to their issuing cursor. |
42 the class and instances has access to their issuing cursor. |
138 |
43 |
139 A property is set for each attribute and relation on each entity's type |
44 A property is set for each attribute and relation on each entity's type |