--- a/schema.py Thu Apr 23 16:10:17 2009 +0200
+++ b/schema.py Thu Apr 23 16:11:30 2009 +0200
@@ -27,7 +27,7 @@
# XXX <3.2 bw compat
from yams import schema
schema.use_py_datetime()
-nodes.use_py_datetime()
+nodes.use_py_datetime()
_ = unicode
@@ -43,7 +43,7 @@
def bw_normalize_etype(etype):
if etype in ETYPE_NAME_MAP:
msg = '%s has been renamed to %s, please update your code' % (
- etype, ETYPE_NAME_MAP[etype])
+ etype, ETYPE_NAME_MAP[etype])
warn(msg, DeprecationWarning, stacklevel=4)
etype = ETYPE_NAME_MAP[etype]
return etype
@@ -78,12 +78,12 @@
class RichString(ybo.String):
"""Convenience RichString attribute type
The follwing declaration::
-
+
class Card(EntityType):
content = RichString(fulltextindexed=True, default_format='text/rest')
-
+
is equivalent to::
-
+
class Card(EntityType):
content_format = String(meta=True, internationalizable=True,
default='text/rest', constraints=[format_constraint])
@@ -106,7 +106,7 @@
constraints=rdef.format_constraints)
yams_add_relation(relations, format_attrdef, name+'_format', insertidx)
yams_add_relation(relations, rdef, name, insertidx)
-
+
def display_name(req, key, form=''):
"""return a internationalized string for the key (schema entity or relation
name) in a given form
@@ -258,19 +258,19 @@
eid = getattr(edef, 'eid', None)
self.eid = eid
# take care: no _groups attribute when deep-copying
- if getattr(self, '_groups', None):
+ if getattr(self, '_groups', None):
for groups in self._groups.itervalues():
for group_or_rqlexpr in groups:
if isinstance(group_or_rqlexpr, RRQLExpression):
msg = "can't use RRQLExpression on an entity type, use an ERQLExpression (%s)"
raise BadSchemaDefinition(msg % self.type)
-
+
def attribute_definitions(self):
"""return an iterator on attribute definitions
-
+
attribute relations are a subset of subject relations where the
object's type is a final entity
-
+
an attribute definition is a 2-uple :
* name of the relation
* schema of the destination entity type
@@ -280,7 +280,7 @@
if rschema.type == 'has_text':
continue
yield rschema, attrschema
-
+
def add_subject_relation(self, rschema):
"""register the relation schema as possible subject relation"""
super(CubicWebEntitySchema, self).add_subject_relation(rschema)
@@ -289,7 +289,7 @@
def del_subject_relation(self, rtype):
super(CubicWebEntitySchema, self).del_subject_relation(rtype)
self._update_has_text(False)
-
+
def _update_has_text(self, need_has_text=None):
may_need_has_text, has_has_text = False, False
for rschema in self.subject_relations():
@@ -317,11 +317,11 @@
self.schema.add_relation_def(rdef)
elif not need_has_text and has_has_text:
self.schema.del_relation_def(self.type, 'has_text', 'String')
-
+
def schema_entity(self):
"""return True if this entity type is used to build the schema"""
return self.type in self.schema.schema_entity_types()
-
+
def check_perm(self, session, action, eid=None):
# NB: session may be a server session or a request object
user = session.user
@@ -337,17 +337,17 @@
# else if there is some rql expressions, check them
if any(rqlexpr.check(session, eid)
for rqlexpr in self.get_rqlexprs(action)):
- return
+ return
raise Unauthorized(action, str(self))
def rql_expression(self, expression, mainvars=None, eid=None):
"""rql expression factory"""
return ERQLExpression(expression, mainvars, eid)
-
+
class CubicWebRelationSchema(RelationSchema):
RelationSchema._RPROPERTIES['eid'] = None
_perms_checked = False
-
+
def __init__(self, schema=None, rdef=None, eid=None, **kwargs):
if rdef is not None:
# if this relation is inlined
@@ -356,8 +356,8 @@
if eid is None and rdef is not None:
eid = getattr(rdef, 'eid', None)
self.eid = eid
-
-
+
+
def update(self, subjschema, objschema, rdef):
super(CubicWebRelationSchema, self).update(subjschema, objschema, rdef)
if not self._perms_checked and self._groups:
@@ -377,7 +377,7 @@
newrqlexprs.append(ERQLExpression(rqlexpr.expression,
rqlexpr.mainvars,
rqlexpr.eid))
- self.set_rqlexprs(action, newrqlexprs)
+ self.set_rqlexprs(action, newrqlexprs)
else:
msg = "can't use RRQLExpression on a final relation "\
"type (eg attribute relation), use an ERQLExpression (%s)"
@@ -388,16 +388,16 @@
"a RRQLExpression (%s)"
raise BadSchemaDefinition(msg % self.type)
self._perms_checked = True
-
+
def cardinality(self, subjtype, objtype, target):
card = self.rproperty(subjtype, objtype, 'cardinality')
return (target == 'subject' and card[0]) or \
(target == 'object' and card[1])
-
+
def schema_relation(self):
return self.type in ('relation_type', 'from_entity', 'to_entity',
'constrained_by', 'cstrtype')
-
+
def physical_mode(self):
"""return an appropriate mode for physical storage of this relation type:
* 'subjectinline' if every possible subject cardinalities are 1 or ?
@@ -413,7 +413,7 @@
# in an allowed group, if so that's enough internal sessions should
# always stop there
if session.user.matching_groups(self.get_groups(action)):
- return
+ return
# else if there is some rql expressions, check them
if any(rqlexpr.check(session, *args, **kwargs)
for rqlexpr in self.get_rqlexprs(action)):
@@ -426,7 +426,7 @@
return ERQLExpression(expression, mainvars, eid)
return RRQLExpression(expression, mainvars, eid)
-
+
class CubicWebSchema(Schema):
"""set of entities and relations schema defining the possible data sets
used in an application
@@ -434,11 +434,11 @@
:type name: str
:ivar name: name of the schema, usually the application identifier
-
+
:type base: str
:ivar base: path of the directory where the schema is defined
"""
- reading_from_database = False
+ reading_from_database = False
entity_class = CubicWebEntitySchema
relation_class = CubicWebRelationSchema
@@ -455,7 +455,7 @@
rschema = self.add_relation_type(ybo.RelationType('identity', meta=True))
rschema.final = False
rschema.set_default_groups()
-
+
def schema_entity_types(self):
"""return the list of entity types used to build the schema"""
return frozenset(('CWEType', 'CWRType', 'CWAttribute', 'CWRelation',
@@ -463,7 +463,7 @@
# XXX those are not really "schema" entity types
# but we usually don't want them as @* targets
'CWProperty', 'CWPermission', 'State', 'Transition'))
-
+
def add_entity_type(self, edef):
edef.name = edef.name.encode()
edef.name = bw_normalize_etype(edef.name)
@@ -478,13 +478,13 @@
self.add_relation_def(rdef)
self._eid_index[eschema.eid] = eschema
return eschema
-
+
def add_relation_type(self, rdef):
rdef.name = rdef.name.lower().encode()
rschema = super(CubicWebSchema, self).add_relation_type(rdef)
self._eid_index[rschema.eid] = rschema
return rschema
-
+
def add_relation_def(self, rdef):
"""build a part of a relation schema
(i.e. add a relation between two specific entity's types)
@@ -511,18 +511,18 @@
self.eschema(rdef.object))
except AttributeError:
pass # not a serialized schema
-
+
def del_relation_type(self, rtype):
rschema = self.rschema(rtype)
self._eid_index.pop(rschema.eid, None)
super(CubicWebSchema, self).del_relation_type(rtype)
-
+
def del_relation_def(self, subjtype, rtype, objtype):
for k, v in self._eid_index.items():
if v == (subjtype, rtype, objtype):
del self._eid_index[k]
super(CubicWebSchema, self).del_relation_def(subjtype, rtype, objtype)
-
+
def del_entity_type(self, etype):
eschema = self.eschema(etype)
self._eid_index.pop(eschema.eid, None)
@@ -531,7 +531,7 @@
if 'has_text' in eschema.subject_relations():
self.del_relation_def(etype, 'has_text', 'String')
super(CubicWebSchema, self).del_entity_type(etype)
-
+
def schema_by_eid(self, eid):
return self._eid_index[eid]
@@ -543,22 +543,22 @@
limit the proposed values to a set of entities returned by a rql query,
but this is not enforced at the repository level
-
+
restriction is additional rql restriction that will be added to
a predefined query, where the S and O variables respectivly represent
the subject and the object of the relation
"""
-
+
def __init__(self, restriction):
self.restriction = restriction
def serialize(self):
return self.restriction
-
+
def deserialize(cls, value):
return cls(value)
deserialize = classmethod(deserialize)
-
+
def check(self, entity, rtype, value):
"""return true if the value satisfy the constraint, else false"""
# implemented as a hook in the repository
@@ -568,7 +568,7 @@
"""raise ValidationError if the relation doesn't satisfy the constraint
"""
pass # this is a vocabulary constraint, not enforce
-
+
def __str__(self):
return self.restriction
@@ -586,7 +586,7 @@
('s', 'o'), build_descr=False)
def error(self, eid, rtype, msg):
raise ValidationError(eid, {rtype: msg})
-
+
def repo_check(self, session, eidfrom, rtype, eidto):
"""raise ValidationError if the relation doesn't satisfy the constraint
"""
@@ -608,12 +608,12 @@
# eidfrom or eidto (from user interface point of view)
self.error(eidfrom, rtype, 'unique constraint %s failed' % self)
-
+
def split_expression(rqlstring):
for expr in rqlstring.split(','):
for word in expr.split():
yield word
-
+
def normalize_expression(rqlstring):
"""normalize an rql expression to ease schema synchronization (avoid
suppressing and reinserting an expression if only a space has been added/removed
@@ -637,19 +637,19 @@
if len(self.rqlst.defined_vars[mainvar].references()) <= 2:
LOGGER.warn('You did not use the %s variable in your RQL expression %s',
mainvar, self)
-
+
def __str__(self):
return self.full_rql
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self.full_rql)
-
+
def __deepcopy__(self, memo):
return self.__class__(self.expression, self.mainvars)
def __getstate__(self):
return (self.expression, self.mainvars)
def __setstate__(self, state):
self.__init__(*state)
-
+
@cached
def transform_has_permission(self):
found = None
@@ -693,7 +693,7 @@
rqlst.recover()
return rql, found, keyarg
return rqlst.as_string(), None, None
-
+
def _check(self, session, **kwargs):
"""return True if the rql expression is matching the given relation
between fromeid and toeid
@@ -753,7 +753,7 @@
if self.eid is not None:
session.local_perm_cache[key] = False
return False
-
+
@property
def minimal_rql(self):
return 'Any %s WHERE %s' % (self.mainvars, self.expression)
@@ -778,16 +778,16 @@
if 'U' in defined:
rql += ', U eid %(u)s'
return rql
-
+
def check(self, session, eid=None):
if 'X' in self.rqlst.defined_vars:
if eid is None:
return False
return self._check(session, x=eid)
return self._check(session)
-
+
PyFileReader.context['ERQLExpression'] = ERQLExpression
-
+
class RRQLExpression(RQLExpression):
def __init__(self, expression, mainvars=None, eid=None):
if mainvars is None:
@@ -817,7 +817,7 @@
if 'U' in defined:
rql += ', U eid %(u)s'
return rql
-
+
def check(self, session, fromeid=None, toeid=None):
kwargs = {}
if 'S' in self.rqlst.defined_vars:
@@ -829,7 +829,7 @@
return False
kwargs['o'] = toeid
return self._check(session, **kwargs)
-
+
PyFileReader.context['RRQLExpression'] = RRQLExpression
# workflow extensions #########################################################
@@ -857,7 +857,7 @@
class WorkflowableEntityType(ybo.EntityType):
__metaclass__ = workflowable_definition
abstract = True
-
+
PyFileReader.context['WorkflowableEntityType'] = WorkflowableEntityType
# schema loading ##############################################################
@@ -866,7 +866,7 @@
"""cubicweb specific relation file reader, handling additional RQL
constraints on a relation definition
"""
-
+
def handle_constraint(self, rdef, constraint_text):
"""arbitrary constraint is an rql expression for cubicweb"""
if not rdef.constraints:
@@ -878,7 +878,7 @@
rdef.inlined = True
RelationFileReader.process_properties(self, rdef, relation_def)
-
+
CONSTRAINTS['RQLConstraint'] = RQLConstraint
CONSTRAINTS['RQLUniqueConstraint'] = RQLUniqueConstraint
CONSTRAINTS['RQLVocabularyConstraint'] = RQLVocabularyConstraint
@@ -900,13 +900,13 @@
self.lib_directory = config.schemas_lib_dir()
return super(BootstrapSchemaLoader, self).load(
path, config.appid, register_base_types=False, **kwargs)
-
+
def _load_definition_files(self, cubes=None):
# bootstraping, ignore cubes
for filepath in self.include_schema_files('bootstrap'):
self.info('loading %s', filepath)
self.handle_file(filepath)
-
+
def unhandled_file(self, filepath):
"""called when a file without handler associated has been found"""
self.warning('ignoring file %r', filepath)
@@ -948,14 +948,14 @@
class FormatConstraint(StaticVocabularyConstraint):
need_perm_formats = [_('text/cubicweb-page-template')]
-
+
regular_formats = (_('text/rest'),
_('text/html'),
_('text/plain'),
)
def __init__(self):
pass
-
+
def serialize(self):
"""called to make persistent valuable data of a constraint"""
return None
@@ -966,18 +966,18 @@
a `cls` instance
"""
return cls()
-
+
def vocabulary(self, entity=None, req=None):
if req is None and entity is not None:
req = entity.req
if req is not None and req.user.has_permission(PERM_USE_TEMPLATE_FORMAT):
return self.regular_formats + tuple(self.need_perm_formats)
return self.regular_formats
-
+
def __str__(self):
return 'value in (%s)' % u', '.join(repr(unicode(word)) for word in self.vocabulary())
-
-
+
+
format_constraint = FormatConstraint()
CONSTRAINTS['FormatConstraint'] = FormatConstraint
PyFileReader.context['format_constraint'] = format_constraint
@@ -992,7 +992,7 @@
def bw_import_erschema(self, ertype, schemamod=None, instantiate=True):
return orig_import_erschema(self, bw_normalize_etype(ertype), schemamod, instantiate)
PyFileReader.import_erschema = bw_import_erschema
-
+
# XXX itou for some Statement methods
from rql import stmts
orig_get_etype = stmts.ScopeNode.get_etype