1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
1 # copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # |
3 # |
4 # This file is part of CubicWeb. |
4 # This file is part of CubicWeb. |
5 # |
5 # |
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
57 # breaks later imports |
57 # breaks later imports |
58 __path__[0] = os.path.abspath(__path__[0]) |
58 __path__[0] = os.path.abspath(__path__[0]) |
59 CW_SOFTWARE_ROOT = __path__[0] |
59 CW_SOFTWARE_ROOT = __path__[0] |
60 |
60 |
61 |
61 |
62 from cubicweb.__pkginfo__ import version as __version__ |
62 from cubicweb.__pkginfo__ import version as __version__ # noqa |
63 |
63 |
64 |
64 |
65 set_log_methods(sys.modules[__name__], logging.getLogger('cubicweb')) |
65 set_log_methods(sys.modules[__name__], logging.getLogger('cubicweb')) |
66 |
66 |
67 # make all exceptions accessible from the package |
67 # make all exceptions accessible from the package |
68 from cubicweb._exceptions import * |
68 from cubicweb._exceptions import * # noqa |
69 from logilab.common.registry import ObjectNotFound, NoSelectableObject, RegistryNotFound |
69 from logilab.common.registry import ObjectNotFound, NoSelectableObject, RegistryNotFound # noqa |
70 |
70 |
71 |
71 |
72 # '_' is available to mark internationalized string but should not be used to |
72 # '_' is available to mark internationalized string but should not be used to |
73 # do the actual translation |
73 # do the actual translation |
74 _ = text_type |
74 _ = text_type |
79 # convert eid to the right type, raise ValueError if it's not a valid eid |
79 # convert eid to the right type, raise ValueError if it's not a valid eid |
80 @deprecated('[3.17] typed_eid() was removed. replace it with int() when needed.') |
80 @deprecated('[3.17] typed_eid() was removed. replace it with int() when needed.') |
81 def typed_eid(eid): |
81 def typed_eid(eid): |
82 return int(eid) |
82 return int(eid) |
83 |
83 |
84 #def log_thread(f, w, a): |
|
85 # print f.f_code.co_filename, f.f_code.co_name |
|
86 #import threading |
|
87 #threading.settrace(log_thread) |
|
88 |
84 |
89 class Binary(BytesIO): |
85 class Binary(BytesIO): |
90 """class to hold binary data. Use BytesIO to prevent use of unicode data""" |
86 """class to hold binary data. Use BytesIO to prevent use of unicode data""" |
91 _allowed_types = (binary_type, bytearray, buffer if PY2 else memoryview) |
87 _allowed_types = (binary_type, bytearray, buffer if PY2 else memoryview) |
92 |
88 |
93 def __init__(self, buf=b''): |
89 def __init__(self, buf=b''): |
94 assert isinstance(buf, self._allowed_types), \ |
90 assert isinstance(buf, self._allowed_types), \ |
95 "Binary objects must use bytes/buffer objects, not %s" % buf.__class__ |
91 "Binary objects must use bytes/buffer objects, not %s" % buf.__class__ |
96 # don't call super, BytesIO may be an old-style class (on python < 2.7.4) |
92 # don't call super, BytesIO may be an old-style class (on python < 2.7.4) |
97 BytesIO.__init__(self, buf) |
93 BytesIO.__init__(self, buf) |
98 |
94 |
99 def write(self, data): |
95 def write(self, data): |
100 assert isinstance(data, self._allowed_types), \ |
96 assert isinstance(data, self._allowed_types), \ |
101 "Binary objects must use bytes/buffer objects, not %s" % data.__class__ |
97 "Binary objects must use bytes/buffer objects, not %s" % data.__class__ |
102 # don't call super, BytesIO may be an old-style class (on python < 2.7.4) |
98 # don't call super, BytesIO may be an old-style class (on python < 2.7.4) |
103 BytesIO.write(self, data) |
99 BytesIO.write(self, data) |
104 |
100 |
105 def to_file(self, fobj): |
101 def to_file(self, fobj): |
106 """write a binary to disk |
102 """write a binary to disk |
147 def __eq__(self, other): |
143 def __eq__(self, other): |
148 if not isinstance(other, Binary): |
144 if not isinstance(other, Binary): |
149 return False |
145 return False |
150 return self.getvalue() == other.getvalue() |
146 return self.getvalue() == other.getvalue() |
151 |
147 |
152 |
|
153 # Binary helpers to store/fetch python objects |
148 # Binary helpers to store/fetch python objects |
154 |
149 |
155 @classmethod |
150 @classmethod |
156 def zpickle(cls, obj): |
151 def zpickle(cls, obj): |
157 """ return a Binary containing a gzipped pickle of obj """ |
152 """ return a Binary containing a gzipped pickle of obj """ |
166 |
161 |
167 def check_password(eschema, value): |
162 def check_password(eschema, value): |
168 return isinstance(value, (binary_type, Binary)) |
163 return isinstance(value, (binary_type, Binary)) |
169 BASE_CHECKERS['Password'] = check_password |
164 BASE_CHECKERS['Password'] = check_password |
170 |
165 |
|
166 |
171 def str_or_binary(value): |
167 def str_or_binary(value): |
172 if isinstance(value, Binary): |
168 if isinstance(value, Binary): |
173 return value |
169 return value |
174 return binary_type(value) |
170 return binary_type(value) |
175 BASE_CONVERTERS['Password'] = str_or_binary |
171 BASE_CONVERTERS['Password'] = str_or_binary |
180 |
176 |
181 # XXX cubic web cube migration map. See if it's worth keeping this mecanism |
177 # XXX cubic web cube migration map. See if it's worth keeping this mecanism |
182 # to help in cube renaming |
178 # to help in cube renaming |
183 CW_MIGRATION_MAP = {} |
179 CW_MIGRATION_MAP = {} |
184 |
180 |
|
181 |
185 def neg_role(role): |
182 def neg_role(role): |
186 if role == 'subject': |
183 if role == 'subject': |
187 return 'object' |
184 return 'object' |
188 return 'subject' |
185 return 'subject' |
|
186 |
189 |
187 |
190 def role(obj): |
188 def role(obj): |
191 try: |
189 try: |
192 return obj.role |
190 return obj.role |
193 except AttributeError: |
191 except AttributeError: |
194 return neg_role(obj.target) |
192 return neg_role(obj.target) |
195 |
193 |
|
194 |
196 def target(obj): |
195 def target(obj): |
197 try: |
196 try: |
198 return obj.target |
197 return obj.target |
199 except AttributeError: |
198 except AttributeError: |
200 return neg_role(obj.role) |
199 return neg_role(obj.role) |
218 """ |
217 """ |
219 def __init__(self): |
218 def __init__(self): |
220 self.callbacks = {} |
219 self.callbacks = {} |
221 |
220 |
222 def bind(self, event, callback, *args, **kwargs): |
221 def bind(self, event, callback, *args, **kwargs): |
223 self.callbacks.setdefault(event, []).append( (callback, args, kwargs) ) |
222 self.callbacks.setdefault(event, []).append((callback, args, kwargs)) |
224 |
223 |
225 def emit(self, event, context=None): |
224 def emit(self, event, context=None): |
226 for callback, args, kwargs in self.callbacks.get(event, ()): |
225 for callback, args, kwargs in self.callbacks.get(event, ()): |
227 if context is None: |
226 if context is None: |
228 callback(*args, **kwargs) |
227 callback(*args, **kwargs) |
229 else: |
228 else: |
230 callback(context, *args, **kwargs) |
229 callback(context, *args, **kwargs) |
231 |
230 |
232 CW_EVENT_MANAGER = CubicWebEventManager() |
231 CW_EVENT_MANAGER = CubicWebEventManager() |
233 |
232 |
|
233 |
234 def onevent(event, *args, **kwargs): |
234 def onevent(event, *args, **kwargs): |
235 """decorator to ease event / callback binding |
235 """decorator to ease event / callback binding |
236 |
236 |
237 >>> from cubicweb import onevent |
237 >>> from cubicweb import onevent |
238 >>> @onevent('before-registry-reload') |
238 >>> @onevent('before-registry-reload') |
246 return func |
246 return func |
247 return _decorator |
247 return _decorator |
248 |
248 |
249 |
249 |
250 from yams.schema import role_name as rname |
250 from yams.schema import role_name as rname |
|
251 |
251 |
252 |
252 def validation_error(entity, errors, substitutions=None, i18nvalues=None): |
253 def validation_error(entity, errors, substitutions=None, i18nvalues=None): |
253 """easy way to retrieve a :class:`cubicweb.ValidationError` for an entity or eid. |
254 """easy way to retrieve a :class:`cubicweb.ValidationError` for an entity or eid. |
254 |
255 |
255 You may also have 2-tuple as error keys, :func:`yams.role_name` will be |
256 You may also have 2-tuple as error keys, :func:`yams.role_name` will be |
270 substitutions, i18nvalues) |
271 substitutions, i18nvalues) |
271 |
272 |
272 |
273 |
273 # exceptions ################################################################## |
274 # exceptions ################################################################## |
274 |
275 |
275 class ProgrammingError(Exception): #DatabaseError): |
276 class ProgrammingError(Exception): |
276 """Exception raised for errors that are related to the database's operation |
277 """Exception raised for errors that are related to the database's operation |
277 and not necessarily under the control of the programmer, e.g. an unexpected |
278 and not necessarily under the control of the programmer, e.g. an unexpected |
278 disconnect occurs, the data source name is not found, a transaction could |
279 disconnect occurs, the data source name is not found, a transaction could |
279 not be processed, a memory allocation error occurred during processing, |
280 not be processed, a memory allocation error occurred during processing, |
280 etc. |
281 etc. |