Index: quintagroup.canonicalpath/tags/0.6/MANIFEST.in
===================================================================
--- quintagroup.canonicalpath/tags/0.6/MANIFEST.in	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/MANIFEST.in	(revision 2155)
@@ -0,0 +1,3 @@
+recursive-include docs *
+recursive-include quintagroup *
+global-exclude *py[co]
Index: quintagroup.canonicalpath/tags/0.6/README.txt
===================================================================
--- quintagroup.canonicalpath/tags/0.6/README.txt	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/README.txt	(revision 2155)
@@ -0,0 +1,44 @@
+Introduction
+============
+
+quintagroup.canonicalpath package brings canonical path calculation 
+functionality to Plone. The package allows to define path and/or link 
+to the object, which may differ from standard physical path or its URL
+in portal.
+
+It's used by such products as quintagroup.seoptimizer (for defining
+canonical link of the object) and quintagroup.plonegooglesitemaps (on
+google sitemaps generation).
+
+This package is intended for bringing *canonical_path* and/or
+*canonical_link* property to any traversable object. For that purpose
+it defines ICanonicalPath and ICanonicalLink interfaces, and registers
+basic adapters for ITraversable objects.
+
+This package also registers *canonical_path* and *canonical_link* indexes
+for possible usage in catalog (ZCatalog).
+
+Default adapters behaviour:
+
+- *canonical_path* returns path from portal root, i.e. for
+    `/plone/front-page` *canonical_path* will be `/front-page`.
+
+- *canonical_link* returns absoulute url of the object.
+
+
+Supported Plone version
+-----------------------
+
+* 3.x
+
+
+Authors
+-------
+
+The product was developed by Quintagroup.com team:
+
+* Andriy Mylenkyi
+* Taras Melnychuk
+* Volodymyr Cherepanyak
+
+Copyright (c) "Quintagroup": http://quintagroup.com, 2004-2010
Index: quintagroup.canonicalpath/tags/0.6/docs/HISTORY.txt
===================================================================
--- quintagroup.canonicalpath/tags/0.6/docs/HISTORY.txt	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/docs/HISTORY.txt	(revision 2155)
@@ -0,0 +1,28 @@
+Changelog
+=========
+
+0.6 (2010-04-20)
+----------------
+
+* added compatibility with plone 3.0-3.3 [fenix]
+* added compatibility for plone 4, removed unnecessary tests [fenix]
+* added delete property functionality for ICanonicalPath,
+  ICanonicalLink [mylan]
+* added ICanonicalLink interface/adapter/tests/indexer [mylan]
+
+
+0.4 (2010-02-11)
+----------------
+
+* Reregistered base adatapter for OFS.interface.ITraversable [mylan]
+* Rewrite indexer registration with help of plone.indexer [mylan]
+* Removed metadata registration in portal catalog [mylan]
+* Added tests [mylan]
+* Added README [mylan]
+
+
+0.1 (2009-03-13)
+----------------
+
+* Initial release
+
Index: quintagroup.canonicalpath/tags/0.6/quintagroup.canonicalpath-configure.zcml
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup.canonicalpath-configure.zcml	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup.canonicalpath-configure.zcml	(revision 2155)
@@ -0,0 +1,1 @@
+<include package="canonicalpath" />
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/__init__.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/__init__.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/__init__.py	(revision 2155)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/README.txt
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/README.txt	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/README.txt	(revision 2155)
@@ -0,0 +1,21 @@
+quintagroup.canonicalpath package brings canonical path calculation 
+functionality to Plone. The package allows to define path and/or link 
+to the object, which may differ from standard physical path or its URL
+in portal.
+
+It's used by such products as quintagroup.seoptimizer (for defining
+canonical link of the object) and quintagroup.plonegooglesitemaps (on
+google sitemaps generation).
+
+This package is intended for bringing *canonical_path* and/or
+*canonical_link* property to any traversable object. For that purpose
+it defines ICanonicalPath and ICanonicalLink interfaces, and registers
+basic adapters for ITraversable objects.
+
+This package also registers *canonical_path* and *canonical_link* indexes
+for possible usage in catalog (ZCatalog).
+
+Default adapters behaviour:
+
+  - *canonical_path* returns path from portal root, i.e. for `/plone/front-page` *canonical_path* will be `/front-page`.
+  - *canonical_link* returns absoulute url of the object.
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/__init__.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/__init__.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/__init__.py	(revision 2155)
@@ -0,0 +1,1 @@
+#
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/adapters.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/adapters.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/adapters.py	(revision 2155)
@@ -0,0 +1,94 @@
+import re
+from zope.interface import implements
+from zope.component import adapts
+from zope.schema.interfaces import InvalidValue
+
+from OFS.interfaces import ITraversable
+from Products.CMFCore.utils import getToolByName
+
+from quintagroup.canonicalpath.interfaces import ICanonicalPath
+from quintagroup.canonicalpath.interfaces import ICanonicalLink
+
+PROPERTY_PATH = "canonical_path"
+PROPERTY_LINK = "canonical_link"
+
+_is_canonical = re.compile(
+    r"\S*$"               # non space and no new line(should be pickier)
+    ).match
+
+
+class DefaultCanonicalAdapter(object):
+    """Generic canonical adapter.
+    """
+    adapts(ITraversable)
+
+    prop = None
+
+    def __init__(self, context):
+        self.context = context
+        self.purl = getToolByName(self.context,'portal_url')
+
+    def _validate(self, value):
+        value.strip()
+        if not _is_canonical(value):
+            raise InvalidValue(value)
+        return value
+
+    def getDefault(self):
+        """Return default value for the self.prop"""
+        raise NotImplementedError()
+
+    def getProp(self):
+        """ First of all return value from the self.prop,
+        if self.prop not exist - return default value
+        """
+        if self.context.hasProperty(self.prop):
+            return self.context.getProperty(self.prop)
+
+        return self.getDefault()
+
+    def setProp(self, value):
+        """ First validate value, than add/updater self.prop
+        """
+        value = self._validate(value)
+
+        if self.context.hasProperty(self.prop):
+            self.context._updateProperty(self.prop, value)
+        else:
+            self.context._setProperty(self.prop, value, type="string")
+
+    def delProp(self):
+        """ Delete self.prop customization
+        """
+        if self.context.hasProperty(self.prop):
+            self.context.manage_delProperties(ids=[self.prop,])
+
+
+class DefaultCanonicalPathAdapter(DefaultCanonicalAdapter):
+    """Adapts base content to canonical path.
+    """
+    implements(ICanonicalPath)
+
+    prop = PROPERTY_PATH
+
+    def getDefault(self):
+        return '/'+'/'.join(self.purl.getRelativeContentPath(self.context))
+
+    canonical_path = property(DefaultCanonicalAdapter.getProp,
+                              DefaultCanonicalAdapter.setProp,
+                              DefaultCanonicalAdapter.delProp)
+
+
+class DefaultCanonicalLinkAdapter(DefaultCanonicalAdapter):
+    """Adapts base content to canonical link.
+    """
+    implements(ICanonicalLink)
+
+    prop = PROPERTY_LINK
+
+    def getDefault(self):
+        return self.context.absolute_url()
+
+    canonical_link = property(DefaultCanonicalAdapter.getProp,
+                              DefaultCanonicalAdapter.setProp,
+                              DefaultCanonicalAdapter.delProp)
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/catalog.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/catalog.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/catalog.py	(revision 2155)
@@ -0,0 +1,46 @@
+from zope.interface import Interface
+from zope.component import queryAdapter
+
+#for compatibility with older plone versions 
+try:
+    from plone.indexer.decorator import indexer 
+    IS_NEW = True
+except:
+    IS_NEW = False
+    class IDummyInterface:pass
+    class indexer:
+
+         def __init__(self, *interfaces):
+            self.interfaces = IDummyInterface,
+
+         def __call__(self, callable):
+             callable.__component_adapts__ = self.interfaces
+             callable.__implemented__ = Interface
+             return callable
+    
+from interfaces import ICanonicalPath
+from interfaces import ICanonicalLink
+
+@indexer(Interface)
+def canonical_path(obj, **kwargs):
+    """Return canonical_path property for the object.
+    """
+    adapter = queryAdapter(obj, interface=ICanonicalPath)
+    if adapter:
+        return adapter.canonical_path
+    return None
+
+@indexer(Interface)
+def canonical_link(obj, **kwargs):
+    """Return canonical_link property for the object.
+    """
+    adapter = queryAdapter(obj, interface=ICanonicalLink)
+    if adapter:
+        return adapter.canonical_link
+    return None
+
+#for compatibility with older plone versions 
+if not IS_NEW:
+    from Products.CMFPlone.CatalogTool import registerIndexableAttribute
+    map(registerIndexableAttribute, ('canonical_path', 'canonical_link'),
+                                    (canonical_path, canonical_link))
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/configure.zcml
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/configure.zcml	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/configure.zcml	(revision 2155)
@@ -0,0 +1,17 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup">
+
+  <!-- Add general canonical_path adapter -->
+  <adapter factory=".adapters.DefaultCanonicalPathAdapter" />
+
+  <!-- Add general canonical_link adapter -->
+  <adapter factory=".adapters.DefaultCanonicalLinkAdapter" />
+
+  <!-- Register canonical_path adapter for catalog -->
+  <adapter name="canonical_path" factory=".catalog.canonical_path" />
+
+  <!-- Register canonical_link adapter for catalog -->
+  <adapter name="canonical_link" factory=".catalog.canonical_link" />
+
+</configure>
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/interfaces.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/interfaces.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/interfaces.py	(revision 2155)
@@ -0,0 +1,18 @@
+from zope.interface import Interface, Attribute
+
+class ICanonicalPath(Interface):
+    """canonical_path provider interface
+    """
+
+    canonical_path = Attribute("canonical_path",
+        "canonical_path - for the object. Adapter must implement "
+        "*setter* and *getter* for the attribute")
+
+class ICanonicalLink(Interface):
+    """canonical_link provider interface
+    """
+
+    canonical_link = Attribute("canonical_link",
+        "canonical_link - for the object. Adapter must implement "
+        "*setter* and *getter* for the attribute")
+
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/tests.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/tests.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/tests.py	(revision 2155)
@@ -0,0 +1,301 @@
+import unittest
+
+from zope.testing import doctestunit
+from zope.component import testing
+from zope.component import queryAdapter, queryMultiAdapter, getMultiAdapter
+from zope.schema.interfaces import InvalidValue
+
+#for compatibility with older plone versions 
+try:
+    from plone.indexer.interfaces import IIndexableObject
+    IS_NEW = True
+except:
+    from plone.app.content.interfaces import IIndexableObjectWrapper \
+        as _old_IIndexableObjectWrapper
+    IS_NEW = False
+
+
+from Testing import ZopeTestCase as ztc
+
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+from Products.CMFCore.utils import getToolByName
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import PloneSite
+
+from Products.Archetypes.tests.utils import makeContent
+
+from quintagroup.canonicalpath.interfaces import ICanonicalPath
+from quintagroup.canonicalpath.interfaces import ICanonicalLink
+from quintagroup.canonicalpath.adapters import PROPERTY_PATH
+from quintagroup.canonicalpath.adapters import PROPERTY_LINK
+
+class TestCase(ptc.PloneTestCase):
+    class layer(PloneSite):
+        @classmethod
+        def setUp(cls):
+            import quintagroup.canonicalpath
+            fiveconfigure.debug_mode = True
+            zcml.load_config('configure.zcml', quintagroup.canonicalpath)
+            fiveconfigure.debug_mode = False
+
+ptc.setupPloneSite()
+
+class TestIndexerRegistration(TestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.catalog = getToolByName(self.portal, 'portal_catalog')
+        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
+        self.logout()
+
+    def get_indexable_wrapper(self, obj):
+        if IS_NEW:
+            wrapper = None
+            if not IIndexableObject.providedBy(obj):
+                wrapper = queryMultiAdapter((obj, self.catalog), IIndexableObject)
+        else:
+            wf = getattr(self.portal, 'portal_workflow', None)
+            if wf is not None:
+                vars = wf.getCatalogVariablesFor(obj)
+            else:
+                vars = {}
+            wrapper = getMultiAdapter((obj, self.portal), _old_IIndexableObjectWrapper)
+            wrapper.update(vars)
+            
+        return wrapper and wrapper or obj
+
+    def testForAT(self):
+        wrapper = self.get_indexable_wrapper(self.my_doc)
+        self.assertFalse(wrapper is None, "No indexer registered for document object")
+
+    def testCanonicalPathForAT(self):
+        wrapper = self.get_indexable_wrapper(self.my_doc)
+        self.assertTrue(hasattr(wrapper, 'canonical_path'),
+            "'canonical_path' attribute not accessible with indexer wrapper for Document object")
+
+    def testCanonicalLinkForAT(self):
+        wrapper = self.get_indexable_wrapper(self.my_doc)
+        self.assertTrue(hasattr(wrapper, 'canonical_link'),
+            "'canonical_link' attribute not accessible with indexer wrapper for Document object")
+
+
+        
+class TestDefaultCanonicalPathAdapter(TestCase):
+
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.purl = getToolByName(self.portal, 'portal_url')
+        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
+        self.logout()
+
+        self.mydoc_cp = '/'+'/'.join(self.purl.getRelativeContentPath(self.my_doc))
+        self.portal_cp = '/'+'/'.join(self.purl.getRelativeContentPath(self.portal))
+
+    def testRegistration4Portal(self):
+        cpadapter = queryAdapter(self.portal, ICanonicalPath)
+        self.assertFalse(cpadapter is None,
+            "Can't get canonical path adapter for the plone site object")
+
+    def testRegistration4AT(self):
+        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
+        self.assertFalse(cpadapter is None,
+            "Can't get canonical path adapter for the Document object")
+        
+
+    def testGetDefault4Portal(self):
+        cpadapter = queryAdapter(self.portal, ICanonicalPath)
+        self.assertTrue(cpadapter.canonical_path == self.portal_cp,
+            "Canonical path adapter return '%s' for portal, must be: '%s'" % (
+            cpadapter.canonical_path, self.portal_cp) )
+
+
+    def testGetDefault4AT(self):
+        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
+        self.assertTrue(cpadapter.canonical_path == self.mydoc_cp,
+            "Canonical path adapter return '%s' for document, must be: '%s'" % (
+            cpadapter.canonical_path, self.mydoc_cp) )
+
+
+    def testSet4Portal(self):
+        cpadapter = queryAdapter(self.portal, ICanonicalPath)
+        newcp = self.portal_cp + '/new_portal_canonical'
+
+        cpadapter.canonical_path = newcp
+        prop = self.portal.getProperty(PROPERTY_PATH, None)
+        self.assertTrue(prop == newcp,
+            "Canonical path adapter setter NOT SET new '%s' value to '%s' " \
+            "propery for the portal" % (newcp, PROPERTY_PATH) )
+
+        self.assertTrue(cpadapter.canonical_path == newcp,
+            "Canonical path adapter GET '%s' canonical_path, for portal, " \
+            "must be: '%s'" % (cpadapter.canonical_path, newcp) )
+
+
+    def testSet4AT(self):
+        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
+        newcp = self.mydoc_cp + '/new_mydoc_canonical'
+
+        cpadapter.canonical_path = newcp
+        prop = self.my_doc.getProperty(PROPERTY_PATH, None)
+        self.assertTrue(prop == newcp,
+            "Canonical path adapter setter NOT SET new '%s' value to '%s' " \
+            "propery for the Document" % (newcp, PROPERTY_PATH) )
+
+        self.assertTrue(cpadapter.canonical_path == newcp,
+            "Canonical path adapter GET '%s' canonical_path, for Document, " \
+            "must be: '%s'" % (cpadapter.canonical_path, newcp) )
+
+
+    def testValidationWrong(self):
+        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
+        for wrong in ['new\nline','s p a c e','with\ttabs']:
+            try:
+                cpadapter.canonical_path = wrong
+            except InvalidValue:
+                continue
+            else:
+                raise self.failureException, "InvalidValue not raised when " \
+                      "'%s' wrong value try to set" % wrong
+        
+    def testValidationGood(self):
+        cpadapter = queryAdapter(self.my_doc, ICanonicalPath)
+        for good in ['./good','../good','/good', 'good']:
+            cpadapter.canonical_path = good
+
+
+    def testDeleteProperty(self):
+        hasprop = self.portal.hasProperty
+        cpadapter = queryAdapter(self.portal, ICanonicalPath)
+        cpadapter.canonical_path = '/new_portal_canonical'
+        assert hasprop(PROPERTY_PATH)
+
+        del cpadapter.canonical_path
+        self.assertFalse(hasprop(PROPERTY_PATH),
+            "Not deleted Canonical path customization property for the portal")
+
+
+    def testDelCustomization(self):
+        cpadapter = queryAdapter(self.portal, ICanonicalPath)
+        cpadapter.canonical_path = '/new_portal_canonical'
+        assert cpadapter.canonical_path == '/new_portal_canonical'
+
+        del cpadapter.canonical_path
+        self.assertTrue(cpadapter.canonical_path == self.portal_cp,
+            "After deleted Canonical path customization property not set to "
+            "default value for the portal")
+
+
+class TestDefaultCanonicalLinkAdapter(TestCase):
+
+    def afterSetUp(self):
+        self.loginAsPortalOwner()
+        self.purl = getToolByName(self.portal, 'portal_url')
+        self.my_doc = makeContent(self.portal, portal_type='Document', id='my_doc')
+        self.logout()
+
+        self.mydoc_cl = self.my_doc.absolute_url()
+
+    def testRegistration4Portal(self):
+        cladapter = queryAdapter(self.portal, ICanonicalLink)
+        self.assertFalse(cladapter is None,
+            "Can't get canonical link adapter for the plone site object")
+
+    def testRegistration4AT(self):
+        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
+        self.assertFalse(cladapter is None,
+            "Can't get canonical link adapter for the Document object")
+        
+
+    def testGetDefault4Portal(self):
+        cladapter = queryAdapter(self.portal, ICanonicalLink)
+        self.assertTrue(cladapter.canonical_link == self.purl(),
+            "Canonical link adapter return '%s' for portal, must be: '%s'" % (
+            cladapter.canonical_link, self.purl()) )
+
+
+    def testGetDefault4AT(self):
+        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
+        self.assertTrue(cladapter.canonical_link == self.mydoc_cl,
+            "Canonical link adapter return '%s' for document, must be: '%s'" % (
+            cladapter.canonical_link, self.mydoc_cl) )
+
+
+    def testSet4Portal(self):
+        cladapter = queryAdapter(self.portal, ICanonicalLink)
+        newcl = self.purl() + '/new_portal_canonical'
+
+        cladapter.canonical_link = newcl
+        prop = self.portal.getProperty(PROPERTY_LINK, None)
+        self.assertTrue(prop == newcl,
+            "Canonical link adapter setter NOT SET new '%s' value to '%s' " \
+            "propery for the portal" % (newcl, PROPERTY_LINK) )
+
+        self.assertTrue(cladapter.canonical_link == newcl,
+            "Canonical link adapter GET '%s' canonical_link, for portal, " \
+            "must be: '%s'" % (cladapter.canonical_link, newcl) )
+
+
+    def testSet4AT(self):
+        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
+        newcl = self.mydoc_cl + '/new_mydoc_canonical'
+
+        cladapter.canonical_link = newcl
+        prop = self.my_doc.getProperty(PROPERTY_LINK, None)
+        self.assertTrue(prop == newcl,
+            "Canonical link adapter setter NOT SET new '%s' value to '%s' " \
+            "propery for the Document" % (newcl, PROPERTY_LINK) )
+
+        self.assertTrue(cladapter.canonical_link == newcl,
+            "Canonical link adapter GET '%s' canonical_link, for Document, " \
+            "must be: '%s'" % (cladapter.canonical_link, newcl) )
+
+    def testValidationWrong(self):
+        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
+        for wrong in ['http://new\nline','s p a c e','with\ttabs']:
+            try:
+                cladapter.canonical_link = wrong
+            except InvalidValue:
+                continue
+            else:
+                raise self.failureException, "InvalidValue not raised when " \
+                    "'%s' wrong value try to set" % wrong
+        
+    def testValidationGood(self):
+        cladapter = queryAdapter(self.my_doc, ICanonicalLink)
+        for good in ['http://', './good','../good','/good', 'good']:
+            cladapter.canonical_link = good
+
+
+    def testDeleteProperty(self):
+        hasprop = self.portal.hasProperty
+        cladapter = queryAdapter(self.portal, ICanonicalLink)
+        cladapter.canonical_link = '/new_portal_canonical'
+        assert hasprop(PROPERTY_LINK)
+
+        del cladapter.canonical_link
+        self.assertFalse(hasprop(PROPERTY_LINK),
+            "Not deleted Canonical link customization property for the portal")
+
+
+    def test_DelCustomization(self):
+        cladapter = queryAdapter(self.portal, ICanonicalLink)
+        cladapter.canonical_link = '/new_portal_canonical'
+        assert cladapter.canonical_link == '/new_portal_canonical'
+
+        del cladapter.canonical_link
+        self.assertTrue(cladapter.canonical_link == self.purl(),
+            "After deleted Canonical link customization property not set to "
+            "default value for the portal")
+
+
+def test_suite():
+    return unittest.TestSuite([
+        unittest.makeSuite(TestIndexerRegistration),
+        unittest.makeSuite(TestDefaultCanonicalPathAdapter),
+        unittest.makeSuite(TestDefaultCanonicalLinkAdapter),
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
Index: quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/version.txt
===================================================================
--- quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/version.txt	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/quintagroup/canonicalpath/version.txt	(revision 2155)
@@ -0,0 +1,1 @@
+0.2
Index: quintagroup.canonicalpath/tags/0.6/setup.cfg
===================================================================
--- quintagroup.canonicalpath/tags/0.6/setup.cfg	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/setup.cfg	(revision 2155)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
Index: quintagroup.canonicalpath/tags/0.6/setup.py
===================================================================
--- quintagroup.canonicalpath/tags/0.6/setup.py	(revision 2155)
+++ quintagroup.canonicalpath/tags/0.6/setup.py	(revision 2155)
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+import os
+
+version = '0.6'
+
+tests_require=['zope.testing']
+setup(name='quintagroup.canonicalpath',
+      version=version,
+      description="Brings canonical path calculation functionality",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='canonical path plone quintagroup',
+      author='Quintagroup',
+      author_email='support@quintagroup.com',
+      url='http://svn.quintagroup.com/products/quintagroup.canonicalpath',
+      license='GPL',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['quintagroup'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+      ],
+      tests_require=tests_require,
+      extras_require=dict(tests=tests_require),
+      test_suite = 'quintagroup.canonicalpath.tests.test_suite',
+      entry_points="""
+      # -*- Entry points: -*-
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      )
+ 
