--- a/cwvreg.py Mon Sep 14 11:38:30 2009 +0200
+++ b/cwvreg.py Mon Sep 14 12:50:27 2009 +0200
@@ -140,9 +140,12 @@
try:
objects = self[btype]
assert len(objects) == 1, objects
- cls = objects[0]
+ if btype == etype:
+ cls = objects[0]
+ else:
+ cls = self.etype_class(btype)
except ObjectNotFound:
- pass
+ continue
else:
# ensure parent classes are built first
self.etype_class(btype)
--- a/entities/lib.py Mon Sep 14 11:38:30 2009 +0200
+++ b/entities/lib.py Mon Sep 14 12:50:27 2009 +0200
@@ -11,6 +11,7 @@
from datetime import datetime
from logilab.common.decorators import cached
+from logilab.common.deprecation import deprecated
from cubicweb import UnknownProperty
from cubicweb.entity import _marker
@@ -25,7 +26,7 @@
class EmailAddress(AnyEntity):
id = 'EmailAddress'
- fetch_attrs, fetch_order = fetch_config(['address', 'alias', 'canonical'])
+ fetch_attrs, fetch_order = fetch_config(['address', 'alias'])
def dc_title(self):
if self.alias:
@@ -36,15 +37,13 @@
def email_of(self):
return self.reverse_use_email and self.reverse_use_email[0]
- @cached
+ @property
+ def prefered(self):
+ return self.prefered_form and self.prefered_form[0] or self
+
+ @deprecated('use .prefered')
def canonical_form(self):
- if self.canonical:
- return self
- rql = 'EmailAddress X WHERE X identical_to Y, X canonical TRUE, Y eid %(y)s'
- cnrset = self.req.execute(rql, {'y': self.eid}, 'y')
- if cnrset:
- return cnrset.get_entity(0, 0)
- return None
+ return self.prefered_form and self.prefered_form[0] or self
def related_emails(self, skipeids=None):
# XXX move to eemail
--- a/entities/test/unittest_base.py Mon Sep 14 11:38:30 2009 +0200
+++ b/entities/test/unittest_base.py Mon Sep 14 12:50:27 2009 +0200
@@ -16,7 +16,6 @@
from cubicweb import ValidationError
from cubicweb.interfaces import IMileStone, IWorkflowable
from cubicweb.entities import AnyEntity
-from cubicweb.entities.authobjs import CWUser
from cubicweb.web.widgets import AutoCompletionWidget
@@ -60,16 +59,13 @@
class EmailAddressTC(BaseEntityTC):
def test_canonical_form(self):
- eid1 = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"')[0][0]
- eid2 = self.execute('INSERT EmailAddress X: X address "maarten@philips.com", X canonical TRUE')[0][0]
- self.execute('SET X identical_to Y WHERE X eid %s, Y eid %s' % (eid1, eid2))
- email1 = self.entity('Any X WHERE X eid %(x)s', {'x':eid1}, 'x')
- email2 = self.entity('Any X WHERE X eid %(x)s', {'x':eid2}, 'x')
- self.assertEquals(email1.canonical_form().eid, eid2)
- self.assertEquals(email2.canonical_form(), email2)
- eid3 = self.execute('INSERT EmailAddress X: X address "toto@logilab.fr"')[0][0]
- email3 = self.entity('Any X WHERE X eid %s'%eid3)
- self.assertEquals(email3.canonical_form(), None)
+ email1 = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"').get_entity(0, 0)
+ email2 = self.execute('INSERT EmailAddress X: X address "maarten@philips.com"').get_entity(0, 0)
+ email3 = self.execute('INSERT EmailAddress X: X address "toto@logilab.fr"').get_entity(0, 0)
+ self.execute('SET X prefered_form Y WHERE X eid %s, Y eid %s' % (email1.eid, email2.eid))
+ self.assertEquals(email1.prefered.eid, email2.eid)
+ self.assertEquals(email2.prefered.eid, email2.eid)
+ self.assertEquals(email3.prefered.eid, email3.eid)
def test_mangling(self):
eid = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"')[0][0]
@@ -102,6 +98,7 @@
class InterfaceTC(EnvBasedTC):
def test_nonregr_subclasses_and_mixins_interfaces(self):
+ CWUser = self.vreg['etypes'].etype_class('CWUser')
self.failUnless(implements(CWUser, IWorkflowable))
class MyUser(CWUser):
__implements__ = (IMileStone,)
@@ -109,9 +106,13 @@
self.vreg.register_appobject_class(MyUser)
self.vreg['etypes'].initialization_completed()
MyUser_ = self.vreg['etypes'].etype_class('CWUser')
- self.failUnless(MyUser is MyUser_)
+ # a copy is done systematically
+ self.failUnless(issubclass(MyUser_, MyUser))
self.failUnless(implements(MyUser_, IMileStone))
self.failUnless(implements(MyUser_, IWorkflowable))
+ # original class should not have beed modified, only the copy
+ self.failUnless(implements(MyUser, IMileStone))
+ self.failIf(implements(MyUser, IWorkflowable))
class SpecializedEntityClassesTC(EnvBasedTC):
@@ -134,11 +135,11 @@
id = etype
self.vreg.register_appobject_class(Foo)
eclass = self.select_eclass('SubDivision')
+ self.failUnless(eclass.__autogenerated__)
if etype == 'SubDivision':
- self.failUnless(eclass is Foo)
+ self.assertEquals(eclass.__bases__, (Foo,))
else:
- self.failUnless(eclass.__autogenerated__)
- self.assertEquals(eclass.__bases__, (Foo,))
+ self.assertEquals(eclass.__bases__[0].__bases__, (Foo,))
# check Division eclass is still selected for plain Division entities
eclass = self.select_eclass('Division')
self.assertEquals(eclass.id, 'Division')
--- a/entities/test/unittest_wfobjs.py Mon Sep 14 11:38:30 2009 +0200
+++ b/entities/test/unittest_wfobjs.py Mon Sep 14 12:50:27 2009 +0200
@@ -335,12 +335,12 @@
self.assertEquals(self.member.state, 'asleep')# no change before commit
self.commit()
self.member.clear_all_caches()
- self.assertEquals(self.member.current_workflow.name, "CWUser workflow")
+ self.assertEquals(self.member.current_workflow.name, "default user workflow")
self.assertEquals(self.member.state, 'activated')
self.assertEquals(parse_hist(self.member.workflow_history),
[('activated', 'deactivated', 'deactivate', None),
('deactivated', 'asleep', None, 'workflow changed to "CWUser"'),
- ('asleep', 'activated', None, 'workflow changed to "CWUser workflow"'),])
+ ('asleep', 'activated', None, 'workflow changed to "default user workflow"'),])
from cubicweb.devtools.apptest import RepositoryBasedTC
--- a/schemas/base.py Mon Sep 14 11:38:30 2009 +0200
+++ b/schemas/base.py Mon Sep 14 12:50:27 2009 +0200
@@ -52,11 +52,10 @@
alias = String(fulltextindexed=True, maxsize=56)
address = String(required=True, fulltextindexed=True,
indexed=True, unique=True, maxsize=128)
- canonical = Boolean(default=False,
- description=_('when multiple addresses are equivalent \
+ prefered_form = SubjectRelation('EmailAddress', cardinality='?*',
+ description=_('when multiple addresses are equivalent \
(such as python-projects@logilab.org and python-projects@lists.logilab.org), set this \
-to true on one of them which is the preferred form.'))
- identical_to = SubjectRelation('EmailAddress')
+to indicate which is the preferred form.'))
class use_email(RelationType):
""" """
@@ -71,9 +70,7 @@
"""the prefered email"""
permissions = use_email.permissions
-class identical_to(RelationType):
- """identical_to"""
- symetric = True
+class prefered_form(RelationType):
permissions = {
'read': ('managers', 'users', 'guests',),
# XXX should have update permissions on both subject and object,
@@ -207,10 +204,6 @@
}
-class see_also(RelationType):
- """generic relation to link one entity to another"""
- symetric = True
-
class ExternalUri(EntityType):
"""a URI representing an object in external data store"""
uri = String(required=True, unique=True, maxsize=256,
@@ -254,3 +247,25 @@
name = String(required=True, unique=True, indexed=True, maxsize=128,
description=_('name of the cache'))
timestamp = Datetime(default='NOW')
+
+
+# "abtract" relation types, not used in cubicweb itself
+
+class identical_to(RelationType):
+ """identical to"""
+ symetric = True
+ permissions = {
+ 'read': ('managers', 'users', 'guests',),
+ # XXX should have update permissions on both subject and object,
+ # though by doing this we will probably have no way to add
+ # this relation in the web ui. The easiest way to acheive this
+ # is probably to be able to have "U has_update_permission O" as
+ # RQLConstraint of the relation definition, though this is not yet
+ # possible
+ 'add': ('managers', RRQLExpression('U has_update_permission S'),),
+ 'delete': ('managers', RRQLExpression('U has_update_permission S'),),
+ }
+
+class see_also(RelationType):
+ """generic relation to link one entity to another"""
+ symetric = True
--- a/test/unittest_schema.py Mon Sep 14 11:38:30 2009 +0200
+++ b/test/unittest_schema.py Mon Sep 14 12:50:27 2009 +0200
@@ -162,7 +162,7 @@
expected_relations = ['add_permission', 'address', 'alias', 'allowed_transition',
'bookmarked_by', 'by_transition',
- 'canonical', 'cardinality', 'comment', 'comment_format',
+ 'cardinality', 'comment', 'comment_format',
'composite', 'condition', 'connait', 'constrained_by', 'content',
'content_format', 'created_by', 'creation_date', 'cstrtype', 'custom_workflow', 'cwuri',
@@ -175,7 +175,7 @@
'from_entity', 'from_state', 'fulltext_container', 'fulltextindexed',
'has_text',
- 'identical_to', 'identity', 'in_group', 'in_state', 'indexed',
+ 'identity', 'in_group', 'in_state', 'indexed',
'initial_state', 'inlined', 'internationalizable', 'is', 'is_instance_of',
'label', 'last_login_time', 'login',
@@ -186,7 +186,7 @@
'ordernum', 'owned_by',
- 'path', 'pkey', 'prenom', 'primary_email',
+ 'path', 'pkey', 'prefered_form', 'prenom', 'primary_email',
'read_permission', 'relation_type', 'require_group',
--- a/web/views/emailaddress.py Mon Sep 14 11:38:30 2009 +0200
+++ b/web/views/emailaddress.py Mon Sep 14 12:50:27 2009 +0200
@@ -24,17 +24,9 @@
def render_entity_attributes(self, entity):
self.w(u'<h3>')
entity.view('oneline', w=self.w)
- if not entity.canonical:
- canonemailaddr = entity.canonical_form()
- if canonemailaddr:
- self.w(u' (<i>%s</i>)' % canonemailaddr.view('oneline'))
- self.w(u'</h3>')
- elif entity.identical_to:
- self.w(u'</h3>')
- identicaladdr = [e.view('oneline') for e in entity.identical_to]
- self.field('identical_to', ', '.join(identicaladdr))
- else:
- self.w(u'</h3>')
+ if entity.prefered:
+ self.w(u' (<i>%s</i>)' % entity.prefered.view('oneline'))
+ self.w(u'</h3>')
try:
persons = entity.reverse_primary_email
except Unauthorized: