[Checkins] SVN: zope.location/trunk/ * Add ``getParents`` method to the ILocationInfo (it's actually used by zope.traversing, but was not added to the interface).

Dan Korostelev nadako at gmail.com
Mon Feb 2 05:59:26 EST 2009


Log message for revision 95958:
  * Add ``getParents`` method to the ILocationInfo (it's actually used by zope.traversing, but was not added to the interface).
  * Beautify doctests and add some more doctests to improve coverage.
  * Add coverage-test and coverage-report to the buildout.
  * Make ``getName`` method of ILocationInfo adapter return u'' for the root object.

Changed:
  _U  zope.location/trunk/
  U   zope.location/trunk/CHANGES.txt
  U   zope.location/trunk/buildout.cfg
  U   zope.location/trunk/src/zope/location/interfaces.py
  U   zope.location/trunk/src/zope/location/location.txt
  U   zope.location/trunk/src/zope/location/pickling.py
  U   zope.location/trunk/src/zope/location/traversing.py

-=-

Property changes on: zope.location/trunk
___________________________________________________________________
Modified: svn:ignore
   - bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg

   + bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg
coverage


Modified: zope.location/trunk/CHANGES.txt
===================================================================
--- zope.location/trunk/CHANGES.txt	2009-02-02 10:27:09 UTC (rev 95957)
+++ zope.location/trunk/CHANGES.txt	2009-02-02 10:59:25 UTC (rev 95958)
@@ -5,6 +5,18 @@
 3.5.1 (unreleased)
 ------------------
 
+- Improve test coverage.
+
+- The new ``getParents`` method was extracted from ``zope.traversing``
+  and added to ILocationInfo interface in the previous release. Custom
+  ILocationInfo implementations should make sure they have this method
+  as well. That method is already used in ``zope.traversing.api.getParents``
+  function.
+
+- Make ``getName`` of ILocationInfo always return empty string for
+  the IRoot object, like RootPhysicallyLocatable from zope.traversing
+  did, making the latter one obsolete.
+
 - Change package mailing list address to zope-dev at zope.org instead
   of retired zope3-dev at zope.org.
 

Modified: zope.location/trunk/buildout.cfg
===================================================================
--- zope.location/trunk/buildout.cfg	2009-02-02 10:27:09 UTC (rev 95957)
+++ zope.location/trunk/buildout.cfg	2009-02-02 10:59:25 UTC (rev 95958)
@@ -1,15 +1,18 @@
 [buildout]
 develop = . 
-parts = test compat
-versions = versions
+parts = test coverage-test coverage-report
 
-[compat]
-recipe = z3c.recipe.compattest
-max_jobs = 3
-
 [test]
 recipe = zc.recipe.testrunner
 eggs = zope.location
 
-[versions]
-ZODB3 = 3.8.1
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = zope.location
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Modified: zope.location/trunk/src/zope/location/interfaces.py
===================================================================
--- zope.location/trunk/src/zope/location/interfaces.py	2009-02-02 10:27:09 UTC (rev 95957)
+++ zope.location/trunk/src/zope/location/interfaces.py	2009-02-02 10:59:25 UTC (rev 95958)
@@ -68,6 +68,15 @@
 
         """
 
+    def getParents():
+        """Returns a list starting with the object's parent followed by
+        each of its parents.
+
+        Raises a TypeError if the object is not connected to a containment
+        root.
+        
+        """
+
     def getName():
         """Return the last segment of the physical path."""
 

Modified: zope.location/trunk/src/zope/location/location.txt
===================================================================
--- zope.location/trunk/src/zope/location/location.txt	2009-02-02 10:27:09 UTC (rev 95957)
+++ zope.location/trunk/src/zope/location/location.txt	2009-02-02 10:59:25 UTC (rev 95958)
@@ -10,144 +10,182 @@
 
 Usage within an Object field:
 
->>> from zope.interface import implements, Interface
->>> from zope.schema import Object
->>> from zope.schema.fieldproperty import FieldProperty
->>> from zope.location.interfaces import ILocation
->>> from zope.location.location import Location
+  >>> from zope.interface import implements, Interface
+  >>> from zope.schema import Object
+  >>> from zope.schema.fieldproperty import FieldProperty
+  >>> from zope.location.interfaces import ILocation
+  >>> from zope.location.location import Location
+  
+  >>> class IA(Interface):
+  ...     location = Object(schema=ILocation, required=False, default=None)
+  >>> class A(object):
+  ...     implements(IA)
+  ...     location = FieldProperty(IA['location'])
+  
+  >>> a = A()
+  >>> a.location = Location()
+  
+  >>> loc = Location(); loc.__name__ = u'foo'
+  >>> a.location = loc
+  
+  >>> loc = Location(); loc.__name__ = None
+  >>> a.location = loc
+  
+  >>> loc = Location(); loc.__name__ = 'foo'
+  >>> a.location = loc
+  Traceback (most recent call last):
+  ...
+  WrongContainedType: [WrongType('foo', <type 'unicode'>)]
 
->>> class IA(Interface):
-...     location = Object(schema=ILocation, required=False, default=None)
->>> class A(object):
-...     implements(IA)
-...     location = FieldProperty(IA['location'])
 
->>> a = A()
->>> a.location = Location()
-
->>> loc = Location(); loc.__name__ = u'foo'
->>> a.location = loc
-
->>> loc = Location(); loc.__name__ = None
->>> a.location = loc
-
->>> loc = Location(); loc.__name__ = 'foo'
->>> a.location = loc
-Traceback (most recent call last):
-...
-WrongContainedType: [WrongType('foo', <type 'unicode'>)]
-
-
 The `inside` Function
 ---------------------
 
 The `inside` function tells if l1 is inside l2.  L1 is inside l2 if l2 is an
 ancestor of l1.
 
->>> o1 = Location()
->>> o2 = Location(); o2.__parent__ = o1
->>> o3 = Location(); o3.__parent__ = o2
->>> o4 = Location(); o4.__parent__ = o3
+  >>> o1 = Location()
+  >>> o2 = Location(); o2.__parent__ = o1
+  >>> o3 = Location(); o3.__parent__ = o2
+  >>> o4 = Location(); o4.__parent__ = o3
+  
+  >>> from zope.location.location import inside
 
->>> from zope.location.location import inside
->>> inside(o1, o1)
-1
->>> inside(o2, o1)
-1
->>> inside(o3, o1)
-1
->>> inside(o4, o1)
-1
+  >>> inside(o1, o1)
+  True
 
->>> inside(o1, o4)
-0
+  >>> inside(o2, o1)
+  True
 
->>> inside(o1, None)
-0
+  >>> inside(o3, o1)
+  True
 
+  >>> inside(o4, o1)
+  True
+  
+  >>> inside(o1, o4)
+  False
+  
+  >>> inside(o1, None)
+  False
 
+
 LocationProxy
 -------------
 
 The LocationProxy is a non-picklable proxy that can be put around
 objects that don't implement `ILocation`.
 
->>> from zope.location.location import LocationProxy
->>> l = [1, 2, 3]
->>> ILocation.providedBy(l)
-False
->>> p = LocationProxy(l, "Dad", "p")
->>> p
-[1, 2, 3]
->>> ILocation.providedBy(p)
-True
->>> p.__parent__
-'Dad'
->>> p.__name__
-'p'
+  >>> from zope.location.location import LocationProxy
+  >>> l = [1, 2, 3]
+  >>> ILocation.providedBy(l)
+  False
+  >>> p = LocationProxy(l, "Dad", "p")
+  >>> p
+  [1, 2, 3]
+  >>> ILocation.providedBy(p)
+  True
+  >>> p.__parent__
+  'Dad'
+  >>> p.__name__
+  'p'
+  
+  >>> import pickle
+  >>> p2 = pickle.dumps(p)
+  Traceback (most recent call last):
+  ...
+  TypeError: Not picklable
 
->>> import pickle
->>> p2 = pickle.dumps(p)
-Traceback (most recent call last):
-...
-TypeError: Not picklable
-
 Proxies should get their doc strings from the object they proxy:
 
->>> p.__doc__ == l.__doc__
-True
+  >>> p.__doc__ == l.__doc__
+  True
 
+If we get a "located class" somehow, its doc string well be available
+through proxy as well:
 
+  >>> class LocalClass(object):
+  ...     """This is class that can be located"""
+
+  >>> p = LocationProxy(LocalClass)
+  >>> p.__doc__ == LocalClass.__doc__
+  True
+
+LocationInterator
+-----------------
+
+This function allows us to iterate over object and all its parents.
+
+  >>> from zope.location.location import LocationIterator
+
+  >>> o1 = Location()
+  >>> o2 = Location()
+  >>> o3 = Location()
+  >>> o3.__parent__ = o2
+  >>> o2.__parent__ = o1
+
+  >>> iter = LocationIterator(o3)
+  >>> iter.next() is o3
+  True
+  >>> iter.next() is o2
+  True
+  >>> iter.next() is o1
+  True
+  >>> iter.next()
+  Traceback (most recent call last):
+  ...
+  StopIteration
+
+
 The `located` function
 ----------------------
 
 `located` locates an object in another and returns it:
 
->>> from zope.location.location import located
->>> a = Location()
->>> parent = Location()
->>> a_located = located(a, parent, 'a')
->>> a_located is a
-True
->>> a_located.__parent__ is parent
-True
->>> a_located.__name__
-'a'
+  >>> from zope.location.location import located
+  >>> a = Location()
+  >>> parent = Location()
+  >>> a_located = located(a, parent, 'a')
+  >>> a_located is a
+  True
+  >>> a_located.__parent__ is parent
+  True
+  >>> a_located.__name__
+  'a'
 
 If we locate the object again, nothing special happens:
 
->>> a_located_2 = located(a_located, parent, 'a')
->>> a_located_2 is a_located
-True
+  >>> a_located_2 = located(a_located, parent, 'a')
+  >>> a_located_2 is a_located
+  True
 
-
 If the object does not provide ILocation an adapter can be provided:
 
->>> import zope.interface
->>> import zope.component
->>> sm = zope.component.getGlobalSiteManager()
->>> sm.registerAdapter(LocationProxy, required=(zope.interface.Interface,))
+  >>> import zope.interface
+  >>> import zope.component
+  >>> sm = zope.component.getGlobalSiteManager()
+  >>> sm.registerAdapter(LocationProxy, required=(zope.interface.Interface,))
+  
+  >>> l = [1, 2, 3]
+  >>> parent = Location()
+  >>> l_located = located(l, parent, 'l')
+  >>> l_located.__parent__ is parent
+  True
+  >>> l_located.__name__
+  'l'
+  >>> l_located is l
+  False
+  >>> type(l_located)
+  <class 'zope.location.location.LocationProxy'>
+  >>> l_located_2 = located(l_located, parent, 'l')
+  >>> l_located_2 is l_located
+  True
 
->>> l = [1, 2, 3]
->>> parent = Location()
->>> l_located = located(l, parent, 'l')
->>> l_located.__parent__ is parent
-True
->>> l_located.__name__
-'l'
->>> l_located is l
-False
->>> type(l_located)
-<class 'zope.location.location.LocationProxy'>
->>> l_located_2 = located(l_located, parent, 'l')
->>> l_located_2 is l_located
-True
-
 When changing the name, we still do not get a different proxied object:
 
->>> l_located_3 = located(l_located, parent, 'new-name')
->>> l_located_3 is l_located_2
-True
+  >>> l_located_3 = located(l_located, parent, 'new-name')
+  >>> l_located_3 is l_located_2
+  True
 
->>> sm.unregisterAdapter(LocationProxy, required=(zope.interface.Interface,))
-True
+  >>> sm.unregisterAdapter(LocationProxy, required=(zope.interface.Interface,))
+  True

Modified: zope.location/trunk/src/zope/location/pickling.py
===================================================================
--- zope.location/trunk/src/zope/location/pickling.py	2009-02-02 10:27:09 UTC (rev 95957)
+++ zope.location/trunk/src/zope/location/pickling.py	2009-02-02 10:59:25 UTC (rev 95958)
@@ -56,15 +56,15 @@
 
     >>> c3 = locationCopy(o1.o3)
     >>> c3 is o1.o3
-    0
+    False
     >>> c3.__parent__ is o1
-    1
+    True
     >>> c3.o5 is o1.o3.o5
-    0
+    False
     >>> c3.o5.__parent__ is c3
-    1
+    True
     >>> c3.o4 is o1.o2.o4
-    1
+    True
 
     """
     tmp = tempfile.TemporaryFile()
@@ -109,27 +109,27 @@
     >>> o3 = Location()
     >>> id3 = persistent.id(o3)
     >>> id3 is None
-    0
+    False
     >>> o4 = Location()
     >>> id4 = persistent.id(o4)
     >>> id4 is None
-    0
+    False
     >>> id4 is id3
-    0
+    False
 
     If we ask for the `id` of an outside location more than once, we
     always get the same `id` back:
 
     >> persistent.id(o4) == id4
-    1
+    True
 
     We also provide a load function that returns the objects for which
     we were given ids:
 
     >>> persistent.load(id3) is o3
-    1
+    True
     >>> persistent.load(id4) is o4
-    1
+    True
 
     """
 
@@ -210,16 +210,23 @@
     >>> persistent.id(o4)
     u'/o3/o4'
 
-    We also provide a load function that returns objects by traversing
+    We also provide a load method that returns objects by traversing
     given paths.  It has to find the root based on the object given to
     the constructor.  Therefore, that object must also be rooted:
 
     >>> o1.__parent__ = root
     >>> persistent.load(u'/o3') is o3
-    1
+    True
     >>> persistent.load(u'/o3/o4') is o4
-    1
+    True
 
+    We must provide an absolute path for the load method:
+
+    >>> persistent.load(u'o3')
+    Traceback (most recent call last):
+    ...
+    ValueError: ('Persistent paths must be absolute', u'o3')
+
     """
 
     def __init__(self, location):
@@ -232,7 +239,7 @@
         return None
 
     def load(self, path):
-        if path[:1] != u'/':
-            raise ValueError("ZPersistent paths must be absolute", path)
+        if not path.startswith(u'/'):
+            raise ValueError("Persistent paths must be absolute", path)
         root = LocationPhysicallyLocatable(self.location).getRoot()
         return zope.location.interfaces.ITraverser(root).traverse(path[1:])

Modified: zope.location/trunk/src/zope/location/traversing.py
===================================================================
--- zope.location/trunk/src/zope/location/traversing.py	2009-02-02 10:27:09 UTC (rev 95957)
+++ zope.location/trunk/src/zope/location/traversing.py	2009-02-02 10:59:25 UTC (rev 95958)
@@ -27,6 +27,12 @@
 
 class LocationPhysicallyLocatable(object):
     """Provide location information for location objects
+    
+    >>> from zope.interface.verify import verifyObject
+    >>> info = LocationPhysicallyLocatable(Location())
+    >>> verifyObject(ILocationInfo, info)
+    True
+    
     """
 
     zope.component.adapts(ILocation)
@@ -46,15 +52,15 @@
         >>> root = Location()
         >>> zope.interface.directlyProvides(root, IRoot)
         >>> LocationPhysicallyLocatable(root).getRoot() is root
-        1
+        True
 
         >>> o1 = Location(); o1.__parent__ = root
         >>> LocationPhysicallyLocatable(o1).getRoot() is root
-        1
+        True
 
         >>> o2 = Location(); o2.__parent__ = o1
         >>> LocationPhysicallyLocatable(o2).getRoot() is root
-        1
+        True
 
         We'll get a TypeError if we try to get the location fo a
         rootless object:
@@ -162,6 +168,27 @@
         Raises a TypeError if the object is not connected to a containment
         root.
 
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(root).getParents()
+        []
+
+        >>> o1 = Location()
+        >>> o2 = Location()
+        >>> o1.__parent__ = root
+        >>> o2.__parent__ = o1
+        >>> LocationPhysicallyLocatable(o2).getParents() == [o1, root]
+        True
+        
+        If the last parent is not an IRoot object, TypeError will be
+        raised as statet before.
+        
+        >>> zope.interface.noLongerProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(o2).getParents()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context information to get all parents
+
         """
         # XXX Merge this implementation with getPath. This was refactored
         # from zope.traversing.
@@ -186,11 +213,18 @@
 
         See ILocationInfo
 
-        >>> o1 = Location(); o1.__name__ = 'o1'
+        >>> o1 = Location(); o1.__name__ = u'o1'
         >>> LocationPhysicallyLocatable(o1).getName()
-        'o1'
+        u'o1'
 
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(root).getName()
+        u''
+
         """
+        if IRoot.providedBy(self.context):
+            return u''
         return self.context.__name__
 
     def getNearestSite(self):
@@ -209,7 +243,17 @@
         >>> o1.__name__ = 'o1'
         >>> o1.__parent__ = root
         >>> LocationPhysicallyLocatable(o1).getNearestSite() is root
-        1
+        True
+        
+        >>> zope.interface.directlyProvides(o1, ISite)
+        >>> LocationPhysicallyLocatable(o1).getNearestSite() is o1
+        True
+        
+        >>> o2 = Location()
+        >>> o2.__parent__ = o1
+        >>> LocationPhysicallyLocatable(o2).getNearestSite() is o1
+        True
+        
         """
         if ISite.providedBy(self.context):
             return self.context



More information about the Checkins mailing list