r13368 - in Products.Archetypes/trunk: . Products/Archetypes Products/Archetypes/interfaces Products/Archetypes/tests
"David Glick" <[email protected]>
| Newsgroups | gmane.comp.web.zope.plone.archetypes.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: davisagli
Date: Mon Dec 20 00:42:24 2010
New Revision: 13368
Added:
Products.Archetypes/trunk/Products/Archetypes/uuid.py
- copied unchanged from r13363, Products.Archetypes/branches/plip10778-plone.uuid/Products/Archetypes/uuid.py
Modified:
Products.Archetypes/trunk/ (props changed)
Products.Archetypes/trunk/CHANGES.txt
Products.Archetypes/trunk/Products/Archetypes/ (props changed)
Products.Archetypes/trunk/Products/Archetypes/Field.py
Products.Archetypes/trunk/Products/Archetypes/ReferenceEngine.py
Products.Archetypes/trunk/Products/Archetypes/Referenceable.py
Products.Archetypes/trunk/Products/Archetypes/UIDCatalog.py
Products.Archetypes/trunk/Products/Archetypes/configure.zcml
Products.Archetypes/trunk/Products/Archetypes/implements.zcml
Products.Archetypes/trunk/Products/Archetypes/interfaces/referenceable.py
Products.Archetypes/trunk/Products/Archetypes/tests/layer.py
Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceCatalog.py
Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceable.py
Products.Archetypes/trunk/Products/Archetypes/utils.py
Products.Archetypes/trunk/setup.py
Log:
merge PLIP 10778
Modified: Products.Archetypes/trunk/CHANGES.txt
==============================================================================
--- Products.Archetypes/trunk/CHANGES.txt (original)
+++ Products.Archetypes/trunk/CHANGES.txt Mon Dec 20 00:42:24 2010
@@ -4,6 +4,19 @@
1.7 - Unreleased
----------------
+- Fix Referenceable, UIDCatalog to support references to non-Archetypes-based
+ content.
+ [toutpt]
+
+- Use the new `plone.uuid` package to generate UUIDs. The UID() method is now
+ an alias for ``IUUID(obj)``, which is the new preferred means of looking up
+ a UUID, since this can also work for non-Archetypes content. Archetypes
+ provides an IUUID() adapter that returns the value stored in the Archetypes
+ UID attribute. For new content, UUIDs are generated using
+ `plone.uuid.interfaces.IUUIDGenerator`, although old content will not (and
+ need not) be migrated.
+ [optilude]
+
- Handle getCharset() returning None in Field.encode/decode.
[elro]
Modified: Products.Archetypes/trunk/Products/Archetypes/Field.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/Field.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/Field.py Mon Dec 20 00:42:24 2010
@@ -90,6 +90,8 @@
from Products.Archetypes.interfaces import IFieldDefaultProvider
+from plone.uuid.interfaces import IUUID
+
# Import conditionally, so we don't introduce a hard depdendency
try:
from plone.i18n.normalizer.interfaces import IUserPreferredFileNameNormalizer
@@ -1780,7 +1782,7 @@
return res
rd = {}
- [rd.__setitem__(r.UID(), r) for r in res]
+ [rd.__setitem__(IUUID(r, None), r) for r in res]
refs = instance.at_ordered_refs
order = refs[self.relationship]
@@ -1861,7 +1863,7 @@
if isinstance(v, basestring):
uids.append(v)
else:
- uids.append(v.UID())
+ uids.append(IUUID(v, None))
add = [v for v in uids if v and v not in targetUIDs]
sub = [t for t in targetUIDs if t not in uids]
@@ -1897,7 +1899,7 @@
relationship
"""
rc = getToolByName(instance, REFERENCE_CATALOG)
- brains = rc(sourceUID=instance.UID(),
+ brains = rc(sourceUID=IUUID(instance, None),
relationship=self.relationship)
res = [b.targetUID for b in brains]
if not self.multiValued and not aslist:
Modified: Products.Archetypes/trunk/Products/Archetypes/ReferenceEngine.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/ReferenceEngine.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/ReferenceEngine.py Mon Dec 20 00:42:24 2010
@@ -31,6 +31,7 @@
from Products.ZCatalog.Catalog import Catalog
from Products import CMFCore
+from plone.uuid.interfaces import IUUID
_www = os.path.join(os.path.dirname(__file__), 'www')
_catalog_dtml = os.path.join(os.path.dirname(CMFCore.__file__), 'dtml')
@@ -84,7 +85,7 @@
def UID(self):
"""the uid method for compat"""
- return getattr(aq_base(self), UUID_ATTR)
+ return IUUID(self, None)
###
# Convenience methods
@@ -494,11 +495,10 @@
if not self.isReferenceable(uobject):
raise ReferenceException, "%r not referenceable" % uobject
- # shasattr() doesn't work here
- if not getattr(aq_base(uobject), UUID_ATTR, None):
+ uuid = IUUID(uobject, None)
+ if uuid is None:
uuid = self._getUUIDFor(uobject)
- else:
- uuid = getattr(uobject, UUID_ATTR)
+
else:
uuid = obj
obj = None
@@ -528,7 +528,7 @@
else:
annotation = sobj._getReferenceAnnotations()
try:
- annotation._delObject(referenceObject.UID())
+ annotation._delObject(IUUID(referenceObject, None))
except (AttributeError, KeyError):
pass
@@ -652,4 +652,3 @@
self._setObject(id, c)
if REQUEST is not None:
return self.manage_main(self, REQUEST,update_menu=1)
-
Modified: Products.Archetypes/trunk/Products/Archetypes/Referenceable.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/Referenceable.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/Referenceable.py Mon Dec 20 00:42:24 2010
@@ -1,5 +1,7 @@
from zope.interface import implements
+from plone.uuid.interfaces import IUUID
+
from Products.Archetypes import config
from Products.Archetypes.exceptions import ReferenceException
from Products.Archetypes.interfaces import IReferenceable
@@ -113,7 +115,7 @@
def _register(self, reference_manager=None):
"""register with the archetype tool for a unique id"""
- if self.UID() is not None:
+ if IUUID(self, None) is not None:
return
if reference_manager is None:
@@ -142,10 +144,10 @@
delattr(self, config.REFERENCE_ANNOTATION)
def UID(self):
- return getattr(self, config.UUID_ATTR, None)
+ return IUUID(self, None)
def _setUID(self, uid):
- old_uid = self.UID()
+ old_uid = IUUID(self, None)
if old_uid is None:
# Nothing to be done.
return
@@ -243,8 +245,11 @@
# TODO Should we ever get here after the isCopy flag addition??
# If the object has no UID or the UID already exists, then
# we should get a new one
- if (not shasattr(self,config.UUID_ATTR) or
- len(uc(UID=self.UID()))):
+
+ uuid = IUUID(self, None)
+
+ if (uuid is None or
+ len(uc(UID=uuid))):
setattr(self, config.UUID_ATTR, None)
self._register()
Modified: Products.Archetypes/trunk/Products/Archetypes/UIDCatalog.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/UIDCatalog.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/UIDCatalog.py Mon Dec 20 00:42:24 2010
@@ -3,6 +3,8 @@
import time
import urllib
from zope.interface import implements
+from zope import component
+from zope import interface
from App.class_init import InitializeClass
from App.special_dtml import DTMLFile
@@ -22,6 +24,9 @@
from Products.Archetypes.config import TOOL_NAME
from Products.Archetypes.interfaces import IUIDCatalog
from Products.Archetypes.utils import getRelURL
+from plone.indexer.interfaces import IIndexableObject
+from plone.indexer.decorator import indexer
+from plone.uuid.interfaces import IUUID, IUUIDAware
_catalog_dtml = os.path.join(os.path.dirname(CMFCore.__file__), 'dtml')
logger = logging.getLogger('Archetypes')
@@ -133,6 +138,21 @@
_marker=[]
+#let rewrite Title indexer with plone.indexer
+@indexer(interface.Interface, IUIDCatalog)
+def Title(obj):
+ title = obj.Title()
+ if isinstance(title, unicode):
+ return title.encode('utf-8')
+ try:
+ return str(title)
+ except UnicodeDecodeError:
+ return obj.getId()
+
+@indexer(IUUIDAware, IUIDCatalog)
+def UID_indexer(obj):
+ return IUUID(obj, None)
+
class UIDResolver(Base):
security = ClassSecurityInfo()
@@ -199,18 +219,16 @@
security.declareProtected(ManageZCatalogEntries, 'catalog_object')
def catalog_object(self, object, uid, idxs=[],
update_metadata=1, pghandler=None):
- w = IndexableObjectWrapper(object)
- try:
- # pghandler argument got added in Zope 2.8
- ZCatalog.catalog_object(self, w, uid, idxs,
- update_metadata, pghandler=pghandler)
- except TypeError:
- try:
- # update_metadata argument got added somewhere into
- # the Zope 2.6 line (?)
- ZCatalog.catalog_object(self, w, uid, idxs, update_metadata)
- except TypeError:
- ZCatalog.catalog_object(self, w, uid, idxs)
+
+ w = object
+ if not IIndexableObject.providedBy(object):
+ # This is the CMF 2.2 compatible approach, which should be used going forward
+ wrapper = component.queryMultiAdapter((object, self), IIndexableObject)
+ if wrapper is not None:
+ w = wrapper
+
+ ZCatalog.catalog_object(self, w, uid, idxs,
+ update_metadata, pghandler=pghandler)
def _catalogObject(self, obj, path):
"""Catalog the object. The object will be cataloged with the absolute
Modified: Products.Archetypes/trunk/Products/Archetypes/configure.zcml
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/configure.zcml (original)
+++ Products.Archetypes/trunk/Products/Archetypes/configure.zcml Mon Dec 20 00:42:24 2010
@@ -10,6 +10,7 @@
package="plone.i18n" />
<include package="plone.folder"/>
+ <include package="plone.uuid" />
<include package="Products.CMFFormController" />
<include package="Products.CMFQuickInstallerTool" />
@@ -34,6 +35,9 @@
<adapter
factory=".traverse.ImageTraverser" />
+ <adapter
+ factory=".uuid.referenceableUUID" />
+
<five:deprecatedManageAddDelete
class=".ReferenceEngine.Reference" />
@@ -70,4 +74,7 @@
<five:deprecatedManageAddDelete
class=".examples.SimpleType.SimpleType" />
+ <adapter factory=".UIDCatalog.Title" name="Title" />
+ <adapter factory=".UIDCatalog.UID_indexer" name="UID" />
+
</configure>
Modified: Products.Archetypes/trunk/Products/Archetypes/implements.zcml
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/implements.zcml (original)
+++ Products.Archetypes/trunk/Products/Archetypes/implements.zcml Mon Dec 20 00:42:24 2010
@@ -6,5 +6,11 @@
zcml:condition="installed plone.locking">
<implements interface="plone.locking.interfaces.ITTWLockable" />
</class>
+
+ <!-- Let all AT objects support the IUUID protocol and associated views -->
+ <class class=".BaseObject.BaseObject"
+ zcml:condition="installed plone.uuid">
+ <implements interface="plone.uuid.interfaces.IUUIDAware" />
+ </class>
</configure>
Modified: Products.Archetypes/trunk/Products/Archetypes/interfaces/referenceable.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/interfaces/referenceable.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/interfaces/referenceable.py Mon Dec 20 00:42:24 2010
@@ -1,6 +1,6 @@
-from zope.interface import Interface
+from plone.uuid.interfaces import IUUIDAware
-class IReferenceable(Interface):
+class IReferenceable(IUUIDAware):
""" Referenceable """
def getRefs(relationship=None):
Modified: Products.Archetypes/trunk/Products/Archetypes/tests/layer.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/tests/layer.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/tests/layer.py Mon Dec 20 00:42:24 2010
@@ -31,6 +31,9 @@
import Products.PlacelessTranslationService
zcml.load_config('configure.zcml', Products.PlacelessTranslationService)
+ import plone.uuid
+ zcml.load_config('configure.zcml', plone.uuid)
+
setUp = classmethod(setUp)
def tearDown(cls):
Modified: Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceCatalog.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceCatalog.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceCatalog.py Mon Dec 20 00:42:24 2010
@@ -22,6 +22,12 @@
# FOR A PARTICULAR PURPOSE.
#
################################################################################
+from zope import component
+from zope import interface
+from zope.event import notify
+from zope.lifecycleevent import ObjectCreatedEvent
+from plone.indexer.interfaces import IIndexableObject
+from Products.ZCatalog.interfaces import IZCatalog
"""
Unittests for a reference Catalog
@@ -36,8 +42,42 @@
from OFS.ObjectManager import BeforeDeleteException
import transaction
+from plone.uuid.interfaces import IAttributeUUID, IUUID
+from plone.indexer import wrapper
+
+class DexterityLike(object):
+ """Create a new class non based on Archetypes"""
+ interface.implements(IAttributeUUID)
+
+ def __init__(self):
+ self.id = "myid"
+ self.portal_type = "dexterity_like"
+ self.path = []
+
+ def Title(self):
+ return u"My dexterity like content"
+
+ def getPhysicalPath(self):
+ if self.path[-1] != self.id:
+ self.path.append(self.id)
+ return self.path
+
+ def manage_fixupOwnershipAfterAdd(self):
+ pass
+
+ def getId(self):
+ return self.id
+
+
class ReferenceCatalogTests(ATSiteTestCase):
+ def afterSetUp(self):
+ #register the test class as indexable with plone.indexer default
+ sm = component.getSiteManager()
+ sm.registerAdapter(factory=wrapper.IndexableObjectWrapper,
+ required=(interface.Interface, IZCatalog),
+ provided=IIndexableObject)
+
def verifyBrains(self):
uc = getattr(self.portal, config.UID_CATALOG)
rc = getattr(self.portal, config.REFERENCE_CATALOG)
@@ -273,7 +313,51 @@
links3 = [o3U, o2U]
obj1.update(sortedlinks=links3)
self.assertEqual(obj1.getRawSortedlinks(), links3)
+ def test_TitleIndexer(self):
+ uc = getattr(self.portal, config.UID_CATALOG)
+ dext = DexterityLike()
+ dext.path = list(self.folder.getPhysicalPath())
+ self.folder[dext.id] = dext
+ uc.catalog_object(dext, '/'.join(dext.getPhysicalPath()))
+ results = uc(Title=dext.Title())
+ self.failUnless(len(results)==1)
+ self.failUnless(type(dext.Title())==unicode)
+ self.failUnless(type(results[0].Title)==str)
+
+ def test_UIDIndexer(self):
+ uc = getattr(self.portal, config.UID_CATALOG)
+ dext = DexterityLike()
+ dext.path = list(self.folder.getPhysicalPath())
+ self.folder[dext.id] = dext
+ notify(ObjectCreatedEvent(dext)) #it supposed to add uuid attribute
+
+ #catalog dext instance
+ uc.catalog_object(dext, '/'.join(dext.getPhysicalPath()))
+
+ #check lookup
+ uuid = IUUID(dext, None)
+ results = uc(UID=uuid)
+
+ self.failUnless(len(results)==1)
+ self.failUnless(results[0].UID==uuid)
+ self.failUnless(results[0].Title==str(dext.Title()))
+
+ def test_reference_non_archetypes_content(self):
+ #create a archetype based content instance
+ ob = makeContent(self.folder, portal_type='DDocument',id='mydocument')
+ uc = getattr(self.portal, config.UID_CATALOG)
+ uc.catalog_object(ob, '/'.join(ob.getPhysicalPath()))
+ #create a non archetype based content
+ dext = DexterityLike()
+ dext.path = list(self.folder.getPhysicalPath())
+ self.folder[dext.id] = dext
+ notify(ObjectCreatedEvent(dext)) #it supposed to add uuid attribute
+ uc.catalog_object(dext, '/'.join(dext.getPhysicalPath()))
+ #TODO: create the relation between those
+ ob.setRelated(dext)
+ related = ob.getRelated()
+ self.failUnless(related==dext)
def test_suite():
from unittest import TestSuite, makeSuite
Modified: Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceable.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceable.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/tests/test_referenceable.py Mon Dec 20 00:42:24 2010
@@ -32,6 +32,7 @@
from Products.Archetypes.examples import *
from Products.Archetypes.config import *
from Products.Archetypes.atapi import DisplayList
+from plone.uuid.interfaces import IUUIDAware, IUUID
class BaseReferenceableTests(ATSiteTestCase):
@@ -64,6 +65,14 @@
self.failUnless(hasattr(aq_base(doc), UUID_ATTR))
self.failUnless(getattr(aq_base(doc), UUID_ATTR, None))
+ def test_uuid(self):
+ doc = makeContent( self.folder
+ , portal_type='DDocument'
+ , title='Foo' )
+
+ self.failUnless(IUUIDAware.providedBy(doc))
+ uuid = IUUID(doc, None)
+ self.failUnless(uuid == doc.UID())
def test_renamedontchangeUID( self ):
catalog = self.portal.uid_catalog
Modified: Products.Archetypes/trunk/Products/Archetypes/utils.py
==============================================================================
--- Products.Archetypes/trunk/Products/Archetypes/utils.py (original)
+++ Products.Archetypes/trunk/Products/Archetypes/utils.py Mon Dec 20 00:42:24 2010
@@ -1,19 +1,12 @@
import logging
import os
-import socket
import sys
-from random import random
-from time import time
from inspect import getargs, getmro
from types import ClassType, MethodType
from UserDict import UserDict as BaseDict
-try:
- from hashlib import md5
-except:
- from md5 import md5
-
import transaction
+from zope.component import getUtility
from zope.i18n import translate
from zope.i18nmessageid import Message
@@ -28,40 +21,14 @@
from Products.Archetypes.config import DEBUG_SECURITY
from Products.statusmessages.interfaces import IStatusMessage
-try:
- _v_network = str(socket.gethostbyname(socket.gethostname()))
-except:
- _v_network = str(random() * 100000000000000000L)
+from plone.uuid.interfaces import IUUIDGenerator
def make_uuid(*args):
- t = str(time() * 1000L)
- r = str(random()*100000000000000000L)
- data = t +' '+ r +' '+ _v_network +' '+ str(args)
- uid = md5(data).hexdigest()
- return uid
-
-# linux kernel uid generator. It's a little bit slower but a little bit better
-KERNEL_UUID = '/proc/sys/kernel/random/uuid'
+ generator = getUtility(IUUIDGenerator)
+ return generator()
logger = logging.getLogger('Archetypes')
-if os.path.isfile(KERNEL_UUID):
- HAS_KERNEL_UUID = True
- def uuid_gen():
- fp = open(KERNEL_UUID, 'r')
- while 1:
- uid = fp.read()[:-1]
- fp.seek(0)
- yield uid
- uid_gen = uuid_gen()
-
- def kernel_make_uuid(*args):
- return uid_gen.next()
-else:
- HAS_KERNEL_UUID = False
- kernel_make_uuid = make_uuid
-
-
def fixSchema(schema):
"""Fix persisted schema from AT < 1.3 (UserDict-based)
to work with the new fixed order schema."""
Modified: Products.Archetypes/trunk/setup.py
==============================================================================
--- Products.Archetypes/trunk/setup.py (original)
+++ Products.Archetypes/trunk/setup.py Mon Dec 20 00:42:24 2010
@@ -62,6 +62,7 @@
'Products.statusmessages',
'Products.validation',
'plone.folder',
+ 'plone.uuid',
'plone.app.folder',
'Acquisition',
'DateTime',
------------------------------------------------------------------------------
Lotusphere 2011
Register now for Lotusphere 2011 and learn how
to connect the dots, take your collaborative environment
to the next level, and enter the era of Social Business.
http://p.sf.net/sfu/lotusphere-d2d