--- a/schema.py Fri Feb 12 15:18:00 2010 +0100
+++ b/schema.py Wed Mar 24 10:23:31 2010 +0100
@@ -15,14 +15,14 @@
from logilab.common.decorators import cached, clear_cache, monkeypatch
from logilab.common.logging_ext import set_log_methods
-from logilab.common.deprecation import deprecated
+from logilab.common.deprecation import deprecated, class_moved
from logilab.common.graph import get_cycles
from logilab.common.compat import any
from yams import BadSchemaDefinition, buildobjs as ybo
-from yams.schema import Schema, ERSchema, EntitySchema, RelationSchema
-from yams.constraints import (BaseConstraint, StaticVocabularyConstraint,
- FormatConstraint)
+from yams.schema import Schema, ERSchema, EntitySchema, RelationSchema, \
+ RelationDefinitionSchema, PermissionMixIn
+from yams.constraints import BaseConstraint, FormatConstraint
from yams.reader import (CONSTRAINTS, PyFileReader, SchemaLoader,
obsolete as yobsolete, cleanup_sys_modules)
@@ -31,11 +31,6 @@
import cubicweb
from cubicweb import ETYPE_NAME_MAP, ValidationError, Unauthorized
-# XXX <3.2 bw compat
-from yams import schema
-schema.use_py_datetime()
-nodes.use_py_datetime()
-
PURE_VIRTUAL_RTYPES = set(('identity', 'has_text',))
VIRTUAL_RTYPES = set(('eid', 'identity', 'has_text',))
@@ -54,6 +49,13 @@
'constrained_by', 'cstrtype',
))
+WORKFLOW_TYPES = set(('Transition', 'State', 'TrInfo', 'Workflow',
+ 'WorkflowTransition', 'BaseTransition',
+ 'SubWorkflowExitPoint'))
+
+INTERNAL_TYPES = set(('CWProperty', 'CWPermission', 'CWCache', 'ExternalUri'))
+
+
_LOGGER = getLogger('cubicweb.schemaloader')
# schema entities created from serialized schema have an eid rproperty
@@ -62,6 +64,31 @@
ybo.RDEF_PROPERTIES += ('eid',)
+PUB_SYSTEM_ENTITY_PERMS = {
+ 'read': ('managers', 'users', 'guests',),
+ 'add': ('managers',),
+ 'delete': ('managers',),
+ 'update': ('managers',),
+ }
+PUB_SYSTEM_REL_PERMS = {
+ 'read': ('managers', 'users', 'guests',),
+ 'add': ('managers',),
+ 'delete': ('managers',),
+ }
+PUB_SYSTEM_ATTR_PERMS = {
+ 'read': ('managers', 'users', 'guests',),
+ 'update': ('managers',),
+ }
+RO_REL_PERMS = {
+ 'read': ('managers', 'users', 'guests',),
+ 'add': (),
+ 'delete': (),
+ }
+RO_ATTR_PERMS = {
+ 'read': ('managers', 'users', 'guests',),
+ 'update': (),
+ }
+
# XXX same algorithm as in reorder_cubes and probably other place,
# may probably extract a generic function
def order_eschemas(eschemas):
@@ -117,7 +144,7 @@
else:
return unicode(req._(key)).lower()
-__builtins__['display_name'] = deprecated('display_name should be imported from cubicweb.schema')(display_name)
+__builtins__['display_name'] = deprecated('[3.4] display_name should be imported from cubicweb.schema')(display_name)
# rql expression utilities function ############################################
@@ -151,15 +178,15 @@
# Schema objects definition ###################################################
-def ERSchema_display_name(self, req, form=''):
+def ERSchema_display_name(self, req, form='', context=None):
"""return a internationalized string for the entity/relation type name in
a given form
"""
- return display_name(req, self.type, form)
+ return display_name(req, self.type, form, context)
ERSchema.display_name = ERSchema_display_name
@cached
-def ERSchema_get_groups(self, action):
+def get_groups(self, action):
"""return the groups authorized to perform <action> on entities of
this type
@@ -172,28 +199,13 @@
assert action in self.ACTIONS, action
#assert action in self._groups, '%s %s' % (self, action)
try:
- return frozenset(g for g in self._groups[action] if isinstance(g, basestring))
+ return frozenset(g for g in self.permissions[action] if isinstance(g, basestring))
except KeyError:
return ()
-ERSchema.get_groups = ERSchema_get_groups
-
-def ERSchema_set_groups(self, action, groups):
- """set the groups allowed to perform <action> on entities of this type. Don't
- change rql expressions for the same action.
-
- :type action: str
- :param action: the name of a permission
-
- :type groups: list or tuple
- :param groups: names of the groups granted to do the given action
- """
- assert action in self.ACTIONS, action
- clear_cache(self, 'ERSchema_get_groups')
- self._groups[action] = tuple(groups) + self.get_rqlexprs(action)
-ERSchema.set_groups = ERSchema_set_groups
+PermissionMixIn.get_groups = get_groups
@cached
-def ERSchema_get_rqlexprs(self, action):
+def get_rqlexprs(self, action):
"""return the rql expressions representing queries to check the user is allowed
to perform <action> on entities of this type
@@ -206,27 +218,13 @@
assert action in self.ACTIONS, action
#assert action in self._rqlexprs, '%s %s' % (self, action)
try:
- return tuple(g for g in self._groups[action] if not isinstance(g, basestring))
+ return tuple(g for g in self.permissions[action] if not isinstance(g, basestring))
except KeyError:
return ()
-ERSchema.get_rqlexprs = ERSchema_get_rqlexprs
-
-def ERSchema_set_rqlexprs(self, action, rqlexprs):
- """set the rql expression allowing to perform <action> on entities of this type. Don't
- change groups for the same action.
-
- :type action: str
- :param action: the name of a permission
+PermissionMixIn.get_rqlexprs = get_rqlexprs
- :type rqlexprs: list or tuple
- :param rqlexprs: the rql expressions allowing the given action
- """
- assert action in self.ACTIONS, action
- clear_cache(self, 'ERSchema_get_rqlexprs')
- self._groups[action] = tuple(self.get_groups(action)) + tuple(rqlexprs)
-ERSchema.set_rqlexprs = ERSchema_set_rqlexprs
-
-def ERSchema_set_permissions(self, action, permissions):
+orig_set_action_permissions = PermissionMixIn.set_action_permissions
+def set_action_permissions(self, action, permissions):
"""set the groups and rql expressions allowing to perform <action> on
entities of this type
@@ -236,22 +234,12 @@
:type permissions: tuple
:param permissions: the groups and rql expressions allowing the given action
"""
- assert action in self.ACTIONS, action
- clear_cache(self, 'ERSchema_get_rqlexprs')
- clear_cache(self, 'ERSchema_get_groups')
- self._groups[action] = tuple(permissions)
-ERSchema.set_permissions = ERSchema_set_permissions
+ orig_set_action_permissions(self, action, tuple(permissions))
+ clear_cache(self, 'get_rqlexprs')
+ clear_cache(self, 'get_groups')
+PermissionMixIn.set_action_permissions = set_action_permissions
-def ERSchema_has_perm(self, session, action, *args, **kwargs):
- """return true if the action is granted globaly or localy"""
- try:
- self.check_perm(session, action, *args, **kwargs)
- return True
- except Unauthorized:
- return False
-ERSchema.has_perm = ERSchema_has_perm
-
-def ERSchema_has_local_role(self, action):
+def has_local_role(self, action):
"""return true if the action *may* be granted localy (eg either rql
expressions or the owners group are used in security definition)
@@ -262,9 +250,73 @@
if self.get_rqlexprs(action):
return True
if action in ('update', 'delete'):
- return self.has_group(action, 'owners')
+ return 'owners' in self.get_groups(action)
return False
-ERSchema.has_local_role = ERSchema_has_local_role
+PermissionMixIn.has_local_role = has_local_role
+
+def may_have_permission(self, action, req):
+ if action != 'read' and not (self.has_local_role('read') or
+ self.has_perm(req, 'read')):
+ return False
+ return self.has_local_role(action) or self.has_perm(req, action)
+PermissionMixIn.may_have_permission = may_have_permission
+
+def has_perm(self, session, action, **kwargs):
+ """return true if the action is granted globaly or localy"""
+ try:
+ self.check_perm(session, action, **kwargs)
+ return True
+ except Unauthorized:
+ return False
+PermissionMixIn.has_perm = has_perm
+
+def check_perm(self, session, action, **kwargs):
+ # NB: session may be a server session or a request object check user is
+ # in an allowed group, if so that's enough internal sessions should
+ # always stop there
+ groups = self.get_groups(action)
+ if session.user.matching_groups(groups):
+ return
+ # if 'owners' in allowed groups, check if the user actually owns this
+ # object, if so that's enough
+ if 'owners' in groups and (
+ kwargs.get('creating')
+ or ('eid' in kwargs and session.user.owns(kwargs['eid']))):
+ return
+ # else if there is some rql expressions, check them
+ if any(rqlexpr.check(session, **kwargs)
+ for rqlexpr in self.get_rqlexprs(action)):
+ return
+ raise Unauthorized(action, str(self))
+PermissionMixIn.check_perm = check_perm
+
+
+RelationDefinitionSchema._RPROPERTIES['eid'] = None
+
+def rql_expression(self, expression, mainvars=None, eid=None):
+ """rql expression factory"""
+ if self.rtype.final:
+ return ERQLExpression(expression, mainvars, eid)
+ return RRQLExpression(expression, mainvars, eid)
+RelationDefinitionSchema.rql_expression = rql_expression
+
+orig_check_permission_definitions = RelationDefinitionSchema.check_permission_definitions
+def check_permission_definitions(self):
+ orig_check_permission_definitions(self)
+ schema = self.subject.schema
+ for action, groups in self.permissions.iteritems():
+ for group_or_rqlexpr in groups:
+ if action == 'read' and \
+ isinstance(group_or_rqlexpr, RQLExpression):
+ msg = "can't use rql expression for read permission of %s"
+ raise BadSchemaDefinition(msg % self)
+ if self.final and isinstance(group_or_rqlexpr, RRQLExpression):
+ msg = "can't use RRQLExpression on %s, use an ERQLExpression"
+ raise BadSchemaDefinition(msg % self)
+ if not self.final and isinstance(group_or_rqlexpr, ERQLExpression):
+ msg = "can't use ERQLExpression on %s, use a RRQLExpression"
+ raise BadSchemaDefinition(msg % self)
+RelationDefinitionSchema.check_permission_definitions = check_permission_definitions
class CubicWebEntitySchema(EntitySchema):
@@ -277,13 +329,14 @@
if eid is None and edef is not None:
eid = getattr(edef, 'eid', None)
self.eid = eid
- # take care: no _groups attribute when deep-copying
- 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 check_permission_definitions(self):
+ super(CubicWebEntitySchema, self).check_permission_definitions()
+ for groups in self.permissions.itervalues():
+ for group_or_rqlexpr in groups:
+ if isinstance(group_or_rqlexpr, RRQLExpression):
+ msg = "can't use RRQLExpression on %s, use an ERQLExpression"
+ raise BadSchemaDefinition(msg % self.type)
def attribute_definitions(self):
"""return an iterator on attribute definitions
@@ -326,7 +379,7 @@
if rschema.final:
if rschema == 'has_text':
has_has_text = True
- elif self.rproperty(rschema, 'fulltextindexed'):
+ elif self.rdef(rschema).get('fulltextindexed'):
may_need_has_text = True
elif rschema.fulltext_container:
if rschema.fulltext_container == 'subject':
@@ -342,7 +395,8 @@
if need_has_text is None:
need_has_text = may_need_has_text
if need_has_text and not has_has_text and not deletion:
- rdef = ybo.RelationDefinition(self.type, 'has_text', 'String')
+ rdef = ybo.RelationDefinition(self.type, 'has_text', 'String',
+ __permissions__=RO_ATTR_PERMS)
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')
@@ -351,32 +405,12 @@
"""return True if this entity type is used to build the schema"""
return self.type in SCHEMA_TYPES
- def check_perm(self, session, action, eid=None):
- # NB: session may be a server session or a request object
- user = session.user
- # check user is in an allowed group, if so that's enough
- # internal sessions should always stop there
- if user.matching_groups(self.get_groups(action)):
- return
- # if 'owners' in allowed groups, check if the user actually owns this
- # object, if so that's enough
- if eid is not None and 'owners' in self.get_groups(action) and \
- user.owns(eid):
- return
- # else if there is some rql expressions, check them
- if any(rqlexpr.check(session, eid)
- for rqlexpr in self.get_rqlexprs(action)):
- 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:
@@ -391,80 +425,69 @@
def meta(self):
return self.type in META_RTYPES
- def update(self, subjschema, objschema, rdef):
- super(CubicWebRelationSchema, self).update(subjschema, objschema, rdef)
- if not self._perms_checked and self._groups:
- for action, groups in self._groups.iteritems():
- for group_or_rqlexpr in groups:
- if action == 'read' and \
- isinstance(group_or_rqlexpr, RQLExpression):
- msg = "can't use rql expression for read permission of "\
- "a relation type (%s)"
- raise BadSchemaDefinition(msg % self.type)
- elif self.final and isinstance(group_or_rqlexpr, RRQLExpression):
- if self.schema.reading_from_database:
- # we didn't have final relation earlier, so turn
- # RRQLExpression into ERQLExpression now
- rqlexpr = group_or_rqlexpr
- newrqlexprs = [x for x in self.get_rqlexprs(action) if not x is rqlexpr]
- newrqlexprs.append(ERQLExpression(rqlexpr.expression,
- rqlexpr.mainvars,
- rqlexpr.eid))
- self.set_rqlexprs(action, newrqlexprs)
- else:
- msg = "can't use RRQLExpression on a final relation "\
- "type (eg attribute relation), use an ERQLExpression (%s)"
- raise BadSchemaDefinition(msg % self.type)
- elif not self.final and \
- isinstance(group_or_rqlexpr, ERQLExpression):
- msg = "can't use ERQLExpression on a relation type, use "\
- "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 True if this relation type is used to build the schema"""
return self.type in SCHEMA_TYPES
- def physical_mode(self):
- """return an appropriate mode for physical storage of this relation type:
- * 'subjectinline' if every possible subject cardinalities are 1 or ?
- * 'objectinline' if 'subjectinline' mode is not possible but every
- possible object cardinalities are 1 or ?
- * None if neither 'subjectinline' and 'objectinline'
- """
- assert not self.final
- return self.inlined and 'subjectinline' or None
+ def may_have_permission(self, action, req, eschema=None, role=None):
+ if eschema is not None:
+ for tschema in self.targets(eschema, role):
+ rdef = self.role_rdef(eschema, tschema, role)
+ if rdef.may_have_permission(action, req):
+ return True
+ else:
+ for rdef in self.rdefs.itervalues():
+ if rdef.may_have_permission(action, req):
+ return True
+ return False
- def check_perm(self, session, action, *args, **kwargs):
- # NB: session may be a server session or a request object check user is
- # 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
- # else if there is some rql expressions, check them
- if any(rqlexpr.check(session, *args, **kwargs)
- for rqlexpr in self.get_rqlexprs(action)):
- return
- raise Unauthorized(action, str(self))
+ def has_perm(self, session, action, **kwargs):
+ """return true if the action is granted globaly or localy"""
+ if self.final:
+ assert not ('fromeid' in kwargs or 'toeid' in kwargs), kwargs
+ assert action in ('read', 'update')
+ if 'eid' in kwargs:
+ subjtype = session.describe(kwargs['eid'])[0]
+ else:
+ subjtype = objtype = None
+ else:
+ assert not 'eid' in kwargs, kwargs
+ assert action in ('read', 'add', 'delete')
+ if 'fromeid' in kwargs:
+ subjtype = session.describe(kwargs['fromeid'])[0]
+ else:
+ subjtype = None
+ if 'toeid' in kwargs:
+ objtype = session.describe(kwargs['toeid'])[0]
+ else:
+ objtype = None
+ if objtype and subjtype:
+ return self.rdef(subjtype, objtype).has_perm(session, action, **kwargs)
+ elif subjtype:
+ for tschema in self.targets(subjtype, 'subject'):
+ rdef = self.rdef(subjtype, tschema)
+ if not rdef.has_perm(session, action, **kwargs):
+ return False
+ elif objtype:
+ for tschema in self.targets(objtype, 'object'):
+ rdef = self.rdef(tschema, objtype)
+ if not rdef.has_perm(session, action, **kwargs):
+ return False
+ else:
+ for rdef in self.rdefs.itervalues():
+ if not rdef.has_perm(session, action, **kwargs):
+ return False
+ return True
- def rql_expression(self, expression, mainvars=None, eid=None):
- """rql expression factory"""
- if self.final:
- return ERQLExpression(expression, mainvars, eid)
- return RRQLExpression(expression, mainvars, eid)
+ @deprecated('use .rdef(subjtype, objtype).role_cardinality(role)')
+ def cardinality(self, subjtype, objtype, target):
+ return self.rdef(subjtype, objtype).role_cardinality(target)
class CubicWebSchema(Schema):
"""set of entities and relations schema defining the possible data sets
used in an application
-
:type name: str
:ivar name: name of the schema, usually the instance identifier
@@ -482,13 +505,10 @@
ybo.register_base_types(self)
rschema = self.add_relation_type(ybo.RelationType('eid'))
rschema.final = True
- rschema.set_default_groups()
rschema = self.add_relation_type(ybo.RelationType('has_text'))
rschema.final = True
- rschema.set_default_groups()
rschema = self.add_relation_type(ybo.RelationType('identity'))
rschema.final = False
- rschema.set_default_groups()
def add_entity_type(self, edef):
edef.name = edef.name.encode()
@@ -498,9 +518,11 @@
if not eschema.final:
# automatically add the eid relation to non final entity types
rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Int',
- cardinality='11', uid=True)
+ cardinality='11', uid=True,
+ __permissions__=RO_ATTR_PERMS)
self.add_relation_def(rdef)
- rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type)
+ rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type,
+ __permissions__=RO_REL_PERMS)
self.add_relation_def(rdef)
self._eid_index[eschema.eid] = eschema
return eschema
@@ -530,13 +552,13 @@
rdef.name = rdef.name.lower()
rdef.subject = bw_normalize_etype(rdef.subject)
rdef.object = bw_normalize_etype(rdef.object)
- if super(CubicWebSchema, self).add_relation_def(rdef):
+ rdefs = super(CubicWebSchema, self).add_relation_def(rdef)
+ if rdefs:
try:
- self._eid_index[rdef.eid] = (self.eschema(rdef.subject),
- self.rschema(rdef.name),
- self.eschema(rdef.object))
+ self._eid_index[rdef.eid] = rdefs
except AttributeError:
pass # not a serialized schema
+ return rdefs
def del_relation_type(self, rtype):
rschema = self.rschema(rtype)
@@ -545,7 +567,9 @@
def del_relation_def(self, subjtype, rtype, objtype):
for k, v in self._eid_index.items():
- if v == (subjtype, rtype, objtype):
+ if not isinstance(v, RelationDefinitionSchema):
+ continue
+ if v.subject == subjtype and v.rtype == rtype and v.object == objtype:
del self._eid_index[k]
break
super(CubicWebSchema, self).del_relation_def(subjtype, rtype, objtype)
@@ -730,6 +754,11 @@
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self.full_rql)
+ def __cmp__(self, other):
+ if hasattr(other, 'expression'):
+ return cmp(other.expression, self.expression)
+ return -1
+
def __deepcopy__(self, memo):
return self.__class__(self.expression, self.mainvars)
def __getstate__(self):
@@ -765,7 +794,7 @@
rqlst.add_selected(objvar)
else:
colindex = selected.index(objvar.name)
- found.append((action, objvar, colindex))
+ found.append((action, colindex))
# remove U eid %(u)s if U is not used in any other relation
uvrefs = rqlst.defined_vars['U'].references()
if len(uvrefs) == 1:
@@ -787,20 +816,25 @@
session may actually be a request as well
"""
- if self.eid is not None:
+ creating = kwargs.get('creating')
+ if not creating and self.eid is not None:
key = (self.eid, tuple(sorted(kwargs.iteritems())))
try:
return session.local_perm_cache[key]
except KeyError:
pass
rql, has_perm_defs, keyarg = self.transform_has_permission()
+ if creating:
+ # when creating an entity, consider has_*_permission satisfied
+ if has_perm_defs:
+ return True
+ return False
if keyarg is None:
# on the server side, use unsafe_execute, but this is not available
# on the client side (session is actually a request)
execute = getattr(session, 'unsafe_execute', session.execute)
- # XXX what if 'u' in kwargs
+ kwargs.setdefault('u', session.user.eid)
cachekey = kwargs.keys()
- kwargs['u'] = session.user.eid
try:
rset = execute(rql, kwargs, cachekey, build_descr=True)
except NotImplementedError:
@@ -828,10 +862,10 @@
# check every special has_*_permission relation is satisfied
get_eschema = session.vreg.schema.eschema
try:
- for eaction, var, col in has_perm_defs:
+ for eaction, col in has_perm_defs:
for i in xrange(len(rset)):
eschema = get_eschema(rset.description[i][col])
- eschema.check_perm(session, eaction, rset[i][col])
+ eschema.check_perm(session, eaction, eid=rset[i][col])
if self.eid is not None:
session.local_perm_cache[key] = True
return True
@@ -864,12 +898,15 @@
rql += ', U eid %(u)s'
return rql
- def check(self, session, eid=None):
+ def check(self, session, eid=None, creating=False, **kwargs):
if 'X' in self.rqlst.defined_vars:
if eid is None:
+ if creating:
+ return self._check(session, creating=True, **kwargs)
return False
- return self._check(session, x=eid)
- return self._check(session)
+ assert creating == False
+ return self._check(session, x=eid, **kwargs)
+ return self._check(session, **kwargs)
class RRQLExpression(RQLExpression):
@@ -918,6 +955,11 @@
kwargs['o'] = toeid
return self._check(session, **kwargs)
+# in yams, default 'update' perm for attributes granted to managers and owners.
+# Within cw, we want to default to users who may edit the entity holding the
+# attribute.
+ybo.DEFAULT_ATTRPERMS['update'] = (
+ 'managers', ERQLExpression('U has_update_permission X'))
# workflow extensions #########################################################
@@ -1036,13 +1078,21 @@
@monkeypatch(FormatConstraint)
def vocabulary(self, entity=None, form=None):
- req = None
+ cw = None
if form is None and entity is not None:
- req = entity.req
+ cw = entity._cw
elif form is not None:
- req = form.req
- if req is not None and req.user.has_permission(PERM_USE_TEMPLATE_FORMAT):
- return self.regular_formats + tuple(NEED_PERM_FORMATS)
+ cw = form._cw
+ if cw is not None:
+ if hasattr(cw, 'is_super_session'):
+ # cw is a server session
+ hasperm = cw.is_super_session or \
+ not cw.vreg.config.is_hook_category_activated('integrity') or \
+ cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT)
+ else:
+ hasperm = cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT)
+ if hasperm:
+ return self.regular_formats + tuple(NEED_PERM_FORMATS)
return self.regular_formats
# XXX monkey patch PyFileReader.import_erschema until bw_normalize_etype is
@@ -1076,10 +1126,14 @@
# XXX deprecated
-from yams.constraints import format_constraint
from yams.buildobjs import RichString
+from yams.constraints import StaticVocabularyConstraint
+
+RichString = class_moved(RichString)
+
+StaticVocabularyConstraint = class_moved(StaticVocabularyConstraint)
+FormatConstraint = class_moved(FormatConstraint)
PyFileReader.context['ERQLExpression'] = yobsolete(ERQLExpression)
PyFileReader.context['RRQLExpression'] = yobsolete(RRQLExpression)
PyFileReader.context['WorkflowableEntityType'] = WorkflowableEntityType
-PyFileReader.context['format_constraint'] = format_constraint