Author: jmorliaguet
Date: Mon Jun  5 23:27:23 2006
New Revision: 3329

Modified:
   cpsskins/branches/paris-sprint-2006/storage/__init__.py
   cpsskins/branches/paris-sprint-2006/storage/configure.zcml
   cpsskins/branches/paris-sprint-2006/storage/storage.py
   cpsskins/branches/paris-sprint-2006/tests/test_storages.py

Log:

- added a name chooser for storages



Modified: cpsskins/branches/paris-sprint-2006/storage/__init__.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/storage/__init__.py     (original)
+++ cpsskins/branches/paris-sprint-2006/storage/__init__.py     Mon Jun  5 
23:27:23 2006
@@ -19,5 +19,5 @@
 
 from zope.deferredimport import defineFrom
 
-defineFrom('cpsskins.storage.storage', 'Storage')
+defineFrom('cpsskins.storage.storage', 'Storage', 'NameChooser')
 

Modified: cpsskins/branches/paris-sprint-2006/storage/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/storage/configure.zcml  (original)
+++ cpsskins/branches/paris-sprint-2006/storage/configure.zcml  Mon Jun  5 
23:27:23 2006
@@ -2,6 +2,13 @@
     xmlns="http://namespaces.zope.org/zope";
     xmlns:cpsskins="http://namespaces.zope.org/cpsskins";>
 
+  <!-- Name chooser for storage items -->
+  <adapter
+      provides="zope.app.container.interfaces.INameChooser"
+      for=".interfaces.IStorage"
+      factory=".storage.NameChooser"
+  />
+
   <!-- Portlet storage -->
   <cpsskins:storage
       id="portlets"

Modified: cpsskins/branches/paris-sprint-2006/storage/storage.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/storage/storage.py      (original)
+++ cpsskins/branches/paris-sprint-2006/storage/storage.py      Mon Jun  5 
23:27:23 2006
@@ -17,6 +17,7 @@
 """
 __docformat__ = "reStructuredText"
 
+import re
 from zope.app.container.btree import BTreeContainer
 from zope.app.container.contained import Contained
 from zope.app.container.contained import ObjectAddedEvent
@@ -31,8 +32,8 @@
 from cpsskins.storage.interfaces import IStorage
 
 class Storage(BTreeContainer, Contained):
-    """A base storage class"""
-
+    """A base storage class.
+    """
     implements(IStorage)
 
     def add(self, object, name=u''):
@@ -76,3 +77,60 @@
 
     def purge(self):
         self.remove(list(self))
+
+
+class NameChooser(object):
+    """Name chooser for storage items.
+
+    Allowed characters are alpha-numeric or minus (-) characters.
+
+    minus characters may not be used at the beginning or at the end of the name
+    and they may not be repeated.
+
+    If a name is already taken, a minus (-) and a number will be appended.
+
+    If a name already ends with a minus and a number, both will be removed to
+    avoid generating names such as: ....-1-2-1-3-3
+
+    """
+    implements(INameChooser)
+
+    def __init__(self, context):
+        self.context = context
+
+    def checkName(self, name, object):
+        if not name:
+            raise ValueError("Empty names are not allowed")
+
+        if not isinstance(name, basestring):
+            raise TypeError("Item names must be strings")
+
+        if self._sanatize(name) != name:
+            raise ValueError("Incorrect name")
+
+        if name in self.context:
+            raise ValueError("The name is already taken")
+
+    def chooseName(self, name, object):
+        if not name:
+            raise ValueError("Empty names are not allowed")
+
+        if not isinstance(name, basestring):
+            raise TypeError("Item names must be strings")
+
+        i = 1
+        n = candidate = re.sub('-[0-9]+$', '', self._sanatize(name))
+        while n in self.context:
+            n = u'%s-%s' % (candidate, i)
+            i += 1
+
+        self.checkName(n, object)
+        return n
+
+    def _sanatize(self, name):
+        name = unicode(name)
+        n = re.sub('[^A-Za-z0-9]+', '-', name)
+        n = re.sub('-+', '-', n)
+        n = re.sub('^-', '', n)
+        n = re.sub('-$', '', n)
+        return n

Modified: cpsskins/branches/paris-sprint-2006/tests/test_storages.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/tests/test_storages.py  (original)
+++ cpsskins/branches/paris-sprint-2006/tests/test_storages.py  Mon Jun  5 
23:27:23 2006
@@ -20,14 +20,56 @@
 import unittest
 
 from zope.testing.doctestunit import DocTestSuite
-from zope.app.testing.placelesssetup import PlacelessSetup
 
 from cpsskins.relations import Predicate, TestRelate as Relate
 from cpsskins.relations import MonadicRelation as Monad
 from cpsskins.relations import DyadicRelation as Dyad, TriadicRelation as Triad
+from cpsskins.storage import Storage, NameChooser
 from cpsskins.storage.relations import RelationStorage
 
-class TestRelationStorage(PlacelessSetup, unittest.TestCase):
+class TestStorageNameChooser(unittest.TestCase):
+
+    def setUp(self):
+        self.storage = Storage()
+        self.chooseName = NameChooser(self.storage).chooseName
+
+    def test_1(self):
+        self.assertEqual(u'123abc', self.chooseName(u'123abc', object()))
+
+    def test_2(self):
+        self.assertEqual(u'123-abc', self.chooseName(u'123-abc', object()))
+
+    def test_3(self):
+        self.assertEqual(u'a', self.chooseName(u'a:/@+', object()))
+
+    def test_4(self):
+        self.assertEqual(u'a-b', self.chooseName(u'a:/@+b', object()))
+
+    def test_5(self):
+        self.assertEqual(u'a-b-c', self.chooseName(u'a:/@+b-c', object()))
+
+    def test_6(self):
+        self.assertEqual(u'a', self.chooseName(u'-a-', object()))
+
+    def test_7(self):
+        self.assertEqual(u'a', self.chooseName(u'a-42', object()))
+
+    def test_8(self):
+        self.assertEqual(u'a-b', self.chooseName(u'a---b', object()))
+
+    def test_9(self):
+        self.storage[u'a'] = object()
+        self.assertEqual(u'a-1', self.chooseName(u'a', object()))
+
+    def test_10(self):
+        self.storage[u'a'] = object()
+        self.storage[u'a-1'] = object()
+        self.assertEqual(u'a-2', self.chooseName(u'a-1', object()))
+
+    def teardown(self):
+        del self.storage
+
+class TestRelationStorage(unittest.TestCase):
 
     def makeTestObject(self):
         return RelationStorage()
@@ -195,6 +237,7 @@
 def test_suite():
     return unittest.TestSuite((
         DocTestSuite('cpsskins.storage.relations'),
+        unittest.makeSuite(TestStorageNameChooser),
         unittest.makeSuite(TestRelationStorage),
         ))
 
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to