[CMF-checkins] SVN: CMF/branches/yuppie-collector467/CMFCore/ - refactored path and registry key handling based on wichert's cmf-dirview-keying-2 patch

Yvo Schubbe y.2007- at wcm-solutions.de
Mon Feb 19 17:44:38 EST 2007


Log message for revision 72697:
  - refactored path and registry key handling based on wichert's cmf-dirview-keying-2 patch

Changed:
  U   CMF/branches/yuppie-collector467/CMFCore/DirectoryView.py
  U   CMF/branches/yuppie-collector467/CMFCore/exportimport/tests/test_skins.py
  U   CMF/branches/yuppie-collector467/CMFCore/tests/__init__.py
  U   CMF/branches/yuppie-collector467/CMFCore/tests/base/testcase.py
  U   CMF/branches/yuppie-collector467/CMFCore/tests/test_DirectoryView.py
  U   CMF/branches/yuppie-collector467/CMFCore/tests/test_utils.py
  U   CMF/branches/yuppie-collector467/CMFCore/utils.py

-=-
Modified: CMF/branches/yuppie-collector467/CMFCore/DirectoryView.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/DirectoryView.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/DirectoryView.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -18,6 +18,7 @@
 import logging
 import re
 from os import path, listdir, stat
+from os.path import abspath
 from sys import platform
 from warnings import warn
 
@@ -27,7 +28,6 @@
 from Globals import DTMLFile
 from Globals import HTMLFile
 from Globals import InitializeClass
-from Globals import package_home
 from Globals import Persistent
 from OFS.Folder import Folder
 from OFS.ObjectManager import bad_id
@@ -39,8 +39,10 @@
 from permissions import AccessContentsInformation
 from permissions import ManagePortal
 from utils import _dtmldir
-from utils import minimalpath
 from utils import normalize
+from utils import getPackageName
+from utils import getPackageLocation
+from utils import ProductsPath
 
 logger = logging.getLogger('CMFCore.DirectoryView')
 
@@ -76,14 +78,35 @@
                     for name in names ]
         listdir.extend(results)
 
+
+def _generateKey(package, subdir):
+    return ':'.join((package, subdir.replace('\\', '/')))
+
+def _findProductForPath(path, subdir=None):
+    # like minimalpath, but raises an error if path is not inside a product
+    p = abspath(path)
+    for ppath in ProductsPath:
+        if p.startswith(ppath):
+            dirpath = p[len(ppath)+1:]
+            parts = dirpath.replace('\\', '/').split('/', 1)
+            parts.append('')
+            if subdir:
+                subdir = '/'.join((parts[1], subdir))
+            else:
+                subdir = parts[1]
+            return ('Products.' + parts[0], subdir)
+
+    raise ValueError('Path is not inside a product')
+
+
 class DirectoryInformation:
     data = None
     _v_last_read = 0
     _v_last_filelist = [] # Only used on Win32
 
-    def __init__(self, filepath, minimal_fp, ignore=ignore):
+    def __init__(self, filepath, reg_key, ignore=ignore):
         self._filepath = filepath
-        self._minimal_fp = minimal_fp
+        self._reg_key = reg_key
         self.ignore=base_ignore + tuple(ignore)
         if platform == 'win32':
             self._walker = _walker(self.ignore)
@@ -182,12 +205,13 @@
             if path.isdir(entry_filepath):
                 # Add a subdirectory only if it was previously registered,
                 # unless register_subdirs is set.
-                entry_minimal_fp = '/'.join( (self._minimal_fp, entry) )
-                info = registry.getDirectoryInfo(entry_minimal_fp)
+                entry_reg_key = '/'.join((self._reg_key, entry))
+                info = registry.getDirectoryInfo(entry_reg_key)
                 if info is None and register_subdirs:
                     # Register unknown subdirs
-                    registry.registerDirectoryByPath(entry_filepath)
-                    info = registry.getDirectoryInfo(entry_minimal_fp)
+                    registry.registerDirectoryByKey(entry_filepath,
+                                                    entry_reg_key)
+                    info = registry.getDirectoryInfo(entry_reg_key)
                 if info is not None:
                     # Folders on the file system have no extension or
                     # meta_type, as a crutch to enable customizing what gets
@@ -203,7 +227,7 @@
                     metadata = FSMetadata(entry_filepath)
                     metadata.read()
                     ob = t( entry
-                          , entry_minimal_fp
+                          , entry_reg_key
                           , properties=metadata.getProperties()
                           )
                     ob_id = ob.getId()
@@ -303,44 +327,91 @@
         # This what is actually called to register a
         # file system directory to become a FSDV.
         if not isinstance(_prefix, basestring):
-            _prefix = package_home(_prefix)
-        filepath = path.join(_prefix, name)
-        self.registerDirectoryByPath(filepath, subdirs, ignore=ignore)
+            package = getPackageName(_prefix)
+            filepath = path.join(getPackageLocation(package), name)
+        else:
+            warn('registerDirectory() called with a path; should be called '
+                 'with globals', DeprecationWarning, stacklevel=2)
+            filepath = path.join(_prefix, name)
+            (package, name) = _findProductForPath(_prefix, name)
+        reg_key = _generateKey(package, name)
+        self.registerDirectoryByKey(filepath, reg_key, subdirs, ignore)
 
-    def registerDirectoryByPath(self, filepath, subdirs=1, ignore=ignore):
-        # This is indirectly called during registration of
-        # a directory. As you can see, minimalpath is called
-        # on the supplied path at this point.
-        # The idea is that the registry will only contain
-        # small paths that are likely to work across platforms
-        # and SOFTWARE_HOME, INSTANCE_HOME and PRODUCTS_PATH setups
-        minimal_fp = minimalpath(filepath)
-        info = DirectoryInformation(filepath, minimal_fp, ignore=ignore)
-        self._directories[minimal_fp] = info
+    def registerDirectoryByKey(self, filepath, reg_key, subdirs=1,
+                               ignore=ignore):
+        info = DirectoryInformation(filepath, reg_key, ignore)
+        self._directories[reg_key] = info
         if subdirs:
             for entry in info.getSubdirs():
                 entry_filepath = path.join(filepath, entry)
-                self.registerDirectoryByPath( entry_filepath
-                                            , subdirs
-                                            , ignore=ignore
-                                            )
+                entry_reg_key = '/'.join((reg_key, entry))
+                self.registerDirectoryByKey(entry_filepath, entry_reg_key,
+                                            subdirs, ignore)
 
-    def reloadDirectory(self, minimal_fp):
-        info = self.getDirectoryInfo(minimal_fp)
+    def registerDirectoryByPath(self, filepath, subdirs=1, ignore=ignore):
+        warn('registerDirectoryByPath() is deprecated and will be removed in '
+             'CMF 2.3. Please use registerDirectoryByKey() instead.',
+             DeprecationWarning, stacklevel=2)
+        (package, subdir) = _findProductForPath(filepath)
+        reg_key = _generateKey(package, subdir)
+        self.registerDirectoryByKey(filepath, reg_key, subdirs, ignore)
+
+    def reloadDirectory(self, reg_key):
+        info = self.getDirectoryInfo(reg_key)
         if info is not None:
             info.reload()
 
-    def getDirectoryInfo(self, minimal_fp):
+    def getDirectoryInfo(self, reg_key):
         # This is called when we need to get hold of the information
         # for a minimal path. Can return None.
-        return self._directories.get(minimal_fp, None)
+        return self._directories.get(reg_key, None)
 
     def listDirectories(self):
         dirs = self._directories.keys()
         dirs.sort()
         return dirs
 
+    def getCurrentKeyFormat(self, reg_key):
+        # BBB: method will be removed in CMF 2.3
 
+        if reg_key in self._directories:
+            return reg_key
+
+        # for DirectoryViews created with CMF versions before 2.1
+        # a path relative to Products/ was used
+        dirpath = reg_key.replace('\\', '/')
+        if dirpath.startswith('Products/'):
+            dirpath = dirpath[9:]
+        product = ['Products']
+        dirparts = dirpath.split('/')
+        while dirparts:
+            product.append(dirparts[0])
+            dirparts = dirparts[1:]
+            possible_key = _generateKey('.'.join(product), '/'.join(dirparts))
+            if possible_key in self._directories:
+                return possible_key
+
+        # for DirectoryViews created with CMF versions before 1.5
+        # this is basically the old minimalpath() code
+        dirpath = normalize(reg_key)
+        index = dirpath.rfind('Products')
+        if index == -1:
+            index = dirpath.rfind('products')
+        if index != -1:
+            dirpath = dirpath[index+len('products/'):]
+            product = ['Products']
+            dirparts = dirpath.split('/')
+            while dirparts:
+                product.append(dirparts[0])
+                dirparts = dirparts[1:]
+                possible_key = _generateKey('.'.join(product),
+                                            '/'.join(dirparts))
+                if possible_key in self._directories:
+                    return possible_key
+
+        raise ValueError('Unsupported key given: %s' % reg_key)
+
+
 _dirreg = DirectoryRegistry()
 registerDirectory = _dirreg.registerDirectory
 registerFileExtension = _dirreg.registerFileExtension
@@ -393,35 +464,29 @@
     _properties = None
     _objects = ()
 
-    def __init__(self, id, dirpath='', fullname=None, properties=None):
+    def __init__(self, id, reg_key='', fullname=None, properties=None):
         if properties:
             # Since props come from the filesystem, this should be
             # safe.
             self.__dict__.update(properties)
 
         self.id = id
-        self._dirpath = dirpath
+        self._dirpath = reg_key
         self._properties = properties
 
     def __of__(self, parent):
-        dirpath = self._dirpath
-        info = _dirreg.getDirectoryInfo(dirpath)
+        reg_key = self._dirpath
+        info = _dirreg.getDirectoryInfo(reg_key)
         if info is None:
-            # for DirectoryViews created with CMF versions before 1.5
-            # this is basically the old minimalpath() code
-            dirpath = normalize(dirpath)
-            index = dirpath.rfind('Products')
-            if index == -1:
-                index = dirpath.rfind('products')
-            if index != -1:
-                dirpath = dirpath[index+len('products/'):]
-            info = _dirreg.getDirectoryInfo(dirpath)
-            if info is not None:
-                # update the directory view with a corrected path
-                self._dirpath = dirpath
-            elif self._dirpath:
-                warn('DirectoryView %s refers to a non-existing path %s'
-                     % (self.id, dirpath), UserWarning)
+            try:
+                reg_key = self._dirpath = _dirreg.getCurrentKeyFormat(reg_key)
+                info = _dirreg.getDirectoryInfo(reg_key)
+            except ValueError:
+                # During GenericSetup a view will be created with an empty
+                # reg_key. This is expected behaviour, so do not warn about it.
+                if reg_key:
+                    warn('DirectoryView %s refers to a non-existing path %r' %
+                          (self.id, reg_key), UserWarning)
         if info is None:
             data = {}
             objects = ()
@@ -471,10 +536,10 @@
     manage_propertiesForm = DTMLFile( 'dirview_properties', _dtmldir )
 
     security.declareProtected(ManagePortal, 'manage_properties')
-    def manage_properties( self, dirpath, REQUEST=None ):
+    def manage_properties(self, reg_key, REQUEST=None):
         """ Update the directory path of the DirectoryView.
         """
-        self.__dict__['_real']._dirpath = dirpath
+        self.__dict__['_real']._dirpath = reg_key
         if REQUEST is not None:
             REQUEST['RESPONSE'].redirect( '%s/manage_propertiesForm'
                                         % self.absolute_url() )
@@ -509,17 +574,17 @@
 
 manage_addDirectoryViewForm = HTMLFile('dtml/addFSDirView', globals())
 
-def createDirectoryView(parent, minimal_fp, id=None):
+def createDirectoryView(parent, reg_key, id=None):
     """ Add either a DirectoryView or a derivative object.
     """
-    info = _dirreg.getDirectoryInfo(minimal_fp)
+    info = _dirreg.getDirectoryInfo(reg_key)
     if info is None:
-        raise ValueError('Not a registered directory: %s' % minimal_fp)
+        raise ValueError('Not a registered directory: %s' % reg_key)
     if not id:
-        id = minimal_fp.split('/')[-1]
+        id = reg_key.split('/')[-1]
     else:
         id = str(id)
-    ob = DirectoryView(id, minimal_fp)
+    ob = DirectoryView(id, reg_key)
     parent._setObject(id, ob)
 
 def addDirectoryViews(ob, name, _prefix):
@@ -530,20 +595,23 @@
     persistence demands.
     """
     if not isinstance(_prefix, basestring):
-        _prefix = package_home(_prefix)
-    filepath = path.join(_prefix, name)
-    minimal_fp = minimalpath(filepath)
-    info = _dirreg.getDirectoryInfo(minimal_fp)
+        package = getPackageName(_prefix)
+    else:
+        warn('addDirectoryViews() called with a path; should be called with '
+             'globals', DeprecationWarning, stacklevel=2)
+        (package, name) = _findProductForPath(_prefix, name)
+    reg_key = _generateKey(package, name)
+    info = _dirreg.getDirectoryInfo(reg_key)
     if info is None:
-        raise ValueError('Not a registered directory: %s' % minimal_fp)
+        raise ValueError('Not a registered directory: %s' % reg_key)
     for entry in info.getSubdirs():
-        entry_minimal_fp = '/'.join( (minimal_fp, entry) )
-        createDirectoryView(ob, entry_minimal_fp, entry)
+        entry_reg_key = '/'.join((reg_key, entry))
+        createDirectoryView(ob, entry_reg_key, entry)
 
-def manage_addDirectoryView(self, dirpath, id=None, REQUEST=None):
+def manage_addDirectoryView(self, reg_key, id=None, REQUEST=None):
     """ Add either a DirectoryView or a derivative object.
     """
-    createDirectoryView(self, dirpath, id)
+    createDirectoryView(self, reg_key, id)
     if REQUEST is not None:
         return self.manage_main(self, REQUEST)
 

Modified: CMF/branches/yuppie-collector467/CMFCore/exportimport/tests/test_skins.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/exportimport/tests/test_skins.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/exportimport/tests/test_skins.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -45,7 +45,7 @@
 <object name="portal_skins" meta_type="CMF Skins Tool" allow_any="False"
    cookie_persistence="False" default_skin="" request_varname="portal_skin">
  <object name="foo_directoryview" meta_type="Filesystem Directory View"
-    directory="CMFCore/exportimport/tests/one"/>
+    directory="Products.CMFCore.exportimport.tests:one"/>
  <skin-path name="foo_path">
   <layer name="one"/>
  </skin-path>
@@ -64,11 +64,11 @@
 <object name="portal_skins" meta_type="Dummy Skins Tool" allow_any="True"
    cookie_persistence="True" default_skin="basic" request_varname="skin_var">
  <object name="one" meta_type="Filesystem Directory View"
-    directory="CMFCore/exportimport/tests/one"/>
+    directory="Products.CMFCore.exportimport.tests:one"/>
  <object name="three" meta_type="Filesystem Directory View"
-    directory="CMFCore/exportimport/tests/three"/>
+    directory="Products.CMFCore.exportimport.tests:three"/>
  <object name="two" meta_type="Filesystem Directory View"
-    directory="CMFCore/exportimport/tests/two"/>
+    directory="Products.CMFCore.exportimport.tests:two"/>
  <skin-path name="basic">
   <layer name="one"/>
  </skin-path>
@@ -84,7 +84,7 @@
 <?xml version="1.0"?>
 <object name="portal_skins" meta_type="Dummy Skins Tool">
  <object name="three" meta_type="Filesystem Directory View"
-    directory="CMFCore/exportimport/tests/three"/>
+    package="Products.CMFCore" path="exportimport/tests/three"/>
  <skin-path name="*">
   <layer name="three" insert-before="two"/>
  </skin-path>
@@ -95,7 +95,7 @@
 <?xml version="1.0"?>
 <object name="portal_skins" meta_type="Dummy Skins Tool">
  <object name="four" meta_type="Filesystem Directory View"
-    directory="CMFCore/exportimport/tests/four"/>
+    directory="Products.CMFCore.exportimport.tests:four"/>
  <skin-path name="*">
   <layer name="four" insert-after="three"/>
  </skin-path>
@@ -189,10 +189,10 @@
         self._olddirreg = DirectoryView._dirreg
         DirectoryView._dirreg = DirectoryView.DirectoryRegistry()
         self._dirreg = DirectoryView._dirreg
-        self._dirreg.registerDirectory('one', _TESTS_PATH)
-        self._dirreg.registerDirectory('two', _TESTS_PATH)
-        self._dirreg.registerDirectory('three', _TESTS_PATH)
-        self._dirreg.registerDirectory('four', _TESTS_PATH)
+        self._dirreg.registerDirectory('one', globals())
+        self._dirreg.registerDirectory('two', globals())
+        self._dirreg.registerDirectory('three', globals())
+        self._dirreg.registerDirectory('four', globals())
 
     def tearDown(self):
         from Products.CMFCore import DirectoryView
@@ -576,6 +576,16 @@
 
 
 def test_suite():
+    # reimport to make sure tests are run from Products
+    from Products.CMFCore.exportimport.tests.test_skins \
+            import DirectoryViewAdapterTests
+    from Products.CMFCore.exportimport.tests.test_skins \
+            import exportSkinsToolTests
+    from Products.CMFCore.exportimport.tests.test_skins \
+            import importSkinsToolTests
+    from Products.CMFCore.exportimport.tests.test_skins \
+            import SkinsToolXMLAdapterTests
+
     return unittest.TestSuite((
         unittest.makeSuite(DirectoryViewAdapterTests),
         unittest.makeSuite(SkinsToolXMLAdapterTests),

Modified: CMF/branches/yuppie-collector467/CMFCore/tests/__init__.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/tests/__init__.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/tests/__init__.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -4,3 +4,5 @@
 As test suites are added, they should be added to the
 mega-test-suite in Products.CMFCore.tests.test_all.py
 """
+
+_globals = globals()

Modified: CMF/branches/yuppie-collector467/CMFCore/tests/base/testcase.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/tests/base/testcase.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/tests/base/testcase.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -18,6 +18,7 @@
 from dummy import DummyFolder
 from security import AnonymousUser
 from security import PermissiveSecurityPolicy
+from Products.CMFCore.utils import getPackageLocation
 
 
 class LogInterceptor:
@@ -208,7 +209,7 @@
 
     def setUp(self):
         # store the place where the skin copy will be created
-        self.tempname = mktemp()
+        self.tempname = mktemp(dir=getPackageLocation('Products.CMFCore.tests'))
         # create the temporary folder
         mkdir(self.tempname)
         # copy the source fake skin to the new location

Modified: CMF/branches/yuppie-collector467/CMFCore/tests/test_DirectoryView.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/tests/test_DirectoryView.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/tests/test_DirectoryView.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -1,14 +1,15 @@
 import unittest
 import Testing
 
+import sys
 from os import remove, mkdir, rmdir
 from os.path import join
 from tempfile import mktemp
 
 from Globals import DevelopmentMode
 
+from Products.CMFCore.tests import _globals
 from Products.CMFCore.tests.base.dummy import DummyFolder
-from Products.CMFCore.tests.base.testcase import _prefix
 from Products.CMFCore.tests.base.testcase import FSDVTest
 from Products.CMFCore.tests.base.testcase import WarningInterceptor
 from Products.CMFCore.tests.base.testcase import WritableFSDVTest
@@ -36,16 +37,36 @@
         self._trap_warning_output()
         from Products.CMFCore.DirectoryView import registerDirectory
         from Products.CMFCore.DirectoryView import addDirectoryViews
-        registerDirectory('fake_skins', _prefix)
+        registerDirectory('fake_skins', _globals)
         self.ob = DummyFolder()
-        addDirectoryViews(self.ob, 'fake_skins', _prefix)
+        addDirectoryViews(self.ob, 'fake_skins', _globals)
 
     def tearDown(self):
         self._free_warning_output()
 
+    def test__generateKey(self):
+        from Products.CMFCore.DirectoryView import _generateKey
+
+        key = _generateKey('Products.CMFCore', 'tests')
+        self.assertEqual(key.split(':')[0], 'Products.CMFCore')
+
+        subkey = _generateKey('Products.CMFCore', 'tests\foo')
+        self.failUnless(subkey.startswith(key))
+
+    def test__findProductForPath(self):
+        from Products.CMFCore.DirectoryView import _findProductForPath
+
+        cmfpath = sys.modules['Products.CMFCore'].__path__[0]
+        self.assertEqual(_findProductForPath(cmfpath),
+                         ('Products.CMFCore', ''))
+
+        cmfpath = join(cmfpath, 'tests')
+        self.assertEqual(_findProductForPath(cmfpath),
+                ('Products.CMFCore', 'tests'))
+
     def test_getDirectoryInfo(self):
         skin = self.ob.fake_skin
-        skin.manage_properties('CMFCore/tests/fake_skins/fake_skin')
+        skin.manage_properties('Products.CMFCore.tests:fake_skins/fake_skin')
         self.failUnless( hasattr(self.ob.fake_skin, 'test1'),
                          self.ob.fake_skin.getDirPath() )
 
@@ -106,6 +127,14 @@
         self.failUnless( hasattr(self.ob.fake_skin, 'test1'),
                          self.ob.fake_skin.getDirPath() )
 
+    # Test pre CMF 2.1 backwards compatibility code in DirectoryView's __of__
+    # method.
+    def test_getDirectoryInfo8(self):
+        skin = self.ob.fake_skin
+        skin.manage_properties('CMFCore/tests/fake_skins/fake_skin')
+        self.failUnless( hasattr(self.ob.fake_skin, 'test1'),
+                         self.ob.fake_skin.getDirPath() )
+
     # Test we do nothing if given a really wacky path
     def test_UnhandleableExpandPath( self ):
         from tempfile import mktemp
@@ -116,8 +145,7 @@
         # Check that a warning was raised.
         from Products.CMFCore import DirectoryView
         warnings = [t[0] for t in DirectoryView.__warningregistry__]
-        text = 'DirectoryView fake_skin refers to a non-existing path %s' % file
-        text = text.replace('\\','/')
+        text = 'DirectoryView fake_skin refers to a non-existing path %r' % file
         self.assert_(text in warnings)
         self.failUnless(text in self._our_stderr_stream.getvalue())
 
@@ -129,16 +157,14 @@
         # normalize in this unit test.
         self.assertEqual( normalize(weirdpath), minimalpath(weirdpath) )
 
-    # this test tests that registerDirectory calls minimalpath correctly
-    # the only way to test this works under SOFTWARE_HOME,INSTANCE_HOME and
-    # PRODUCTS_PATH setups is to run the test in those environments
-    def test_registerDirectoryMinimalPath(self):
+    # this test tests that registerDirectory creates keys in the right format.
+    def test_registerDirectoryKeys(self):
         from Products.CMFCore.DirectoryView import _dirreg
         dirs = _dirreg._directories
-        self.failUnless( dirs.has_key('CMFCore/tests/fake_skins/fake_skin'),
+        self.failUnless( dirs.has_key('Products.CMFCore.tests:fake_skins/fake_skin'),
                          dirs.keys() )
         self.assertEqual( self.ob.fake_skin.getDirPath(),
-                          'CMFCore/tests/fake_skins/fake_skin' )
+                          'Products.CMFCore.tests:fake_skins/fake_skin' )
 
 
 class DirectoryViewTests( FSDVTest ):

Modified: CMF/branches/yuppie-collector467/CMFCore/tests/test_utils.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/tests/test_utils.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/tests/test_utils.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -61,7 +61,24 @@
             self.assertEqual( contributorsplitter({'Contributors': x}), 
                               ['foo', 'bar', 'baz'] )
 
+    def test_getPackageName(self):
+        from Products.CMFCore.utils import getPackageName
+        from Products.CMFCore.utils import _globals
 
+        self.assertEqual(getPackageName(globals()), 'Products.CMFCore.tests')
+        self.assertEqual(getPackageName(_globals), 'Products.CMFCore')
+
+    def test_getContainingPackage(self):
+        from Products.CMFCore.utils import getContainingPackage
+
+        self.assertEqual(getContainingPackage('Products.CMFCore.exceptions'),
+                'Products.CMFCore')
+        self.assertEqual(getContainingPackage('Products.CMFCore'),
+                'Products.CMFCore')
+        self.assertEqual(getContainingPackage('zope.interface.verify'),
+                'zope.interface')
+
+
 class CoreUtilsSecurityTests(SecurityTest):
 
     def _makeSite(self):
@@ -130,6 +147,9 @@
 
 
 def test_suite():
+    # reimport to make sure tests are run from Products
+    from Products.CMFCore.tests.test_utils import CoreUtilsTests
+
     return unittest.TestSuite((
         unittest.makeSuite(CoreUtilsTests),
         unittest.makeSuite(CoreUtilsSecurityTests),

Modified: CMF/branches/yuppie-collector467/CMFCore/utils.py
===================================================================
--- CMF/branches/yuppie-collector467/CMFCore/utils.py	2007-02-19 22:18:15 UTC (rev 72696)
+++ CMF/branches/yuppie-collector467/CMFCore/utils.py	2007-02-19 22:44:37 UTC (rev 72697)
@@ -20,6 +20,7 @@
 from os import path as os_path
 from os.path import abspath
 from warnings import warn
+import sys
 
 from AccessControl import ClassSecurityInfo
 from AccessControl import getSecurityManager
@@ -55,6 +56,7 @@
 
 security = ModuleSecurityInfo( 'Products.CMFCore.utils' )
 
+_globals = globals()
 _dtmldir = os_path.join( package_home( globals() ), 'dtml' )
 _wwwdir = os_path.join( package_home( globals() ), 'www' )
 
@@ -728,6 +730,9 @@
     The (expanded) filepath is the valid absolute path on the current platform
     and setup.
     """
+    warn('expandpath() is deprecated and will be removed in CMF 2.3.',
+         DeprecationWarning, stacklevel=2)
+
     p = os_path.normpath(p)
     if os_path.isabs(p):
         return p
@@ -751,6 +756,9 @@
     Returns a slash-separated path relative to the Products path. If it can't
     be found, a normalized path is returned.
     """
+    warn('minimalpath() is deprecated and will be removed in CMF 2.3.',
+         DeprecationWarning, stacklevel=2)
+
     p = abspath(p)
     for ppath in ProductsPath:
         if p.startswith(ppath):
@@ -758,6 +766,33 @@
             break
     return p.replace('\\','/')
 
+security.declarePrivate('getContainingPackage')
+def getContainingPackage(module):
+    parts = module.split(".")
+    while parts:
+        name = ".".join(parts)
+        mod = sys.modules[name]
+        if "__init__" in mod.__file__:
+            return name
+        parts = parts[:-1]
+
+    raise ValueError('Unable to find package for module %s' % module)
+
+security.declarePrivate('getPackageLocation')
+def getPackageLocation(module):
+    """ Return the filesystem location of a module.
+
+    This is a simple wrapper around the global package_home method which
+    tricks it into working with just a module name.
+    """
+    package = getContainingPackage(module)
+    return package_home({'__name__' : package})
+
+security.declarePrivate('getPackageName')
+def getPackageName(globals_):
+    module = globals_['__name__']
+    return getContainingPackage(module)
+
 def _OldCacheHeaders(obj):
     # Old-style checking of modified headers
 



More information about the CMF-checkins mailing list