Back to index

plone3  3.1.7
utils.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights
00004 # Reserved.
00005 #
00006 # This software is subject to the provisions of the Zope Public License,
00007 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this
00008 # distribution.
00009 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00010 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00011 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00012 # FOR A PARTICULAR PURPOSE.
00013 #
00014 ##############################################################################
00015 import os
00016 import sha
00017 import unittest
00018 
00019 from Globals import package_home
00020 
00021 try:
00022     from Products.Five.bridge import fromZ2Interface
00023 except ImportError:
00024     def fromZ2Interface(i):
00025         # Raise ValueError to work around a cornerish case where
00026         # zope.interface is available but Five is not.
00027         raise ValueError, i
00028 
00029 from zope import interface
00030 def directlyProvides(obj, *interfaces):
00031     # convert any Zope 2 interfaces to Zope 3 using fromZ2Interface
00032     normalized_interfaces = []
00033     for i in interfaces:
00034         try:
00035             i = fromZ2Interface(i)
00036         except ValueError: # already a Zope 3 interface
00037             pass
00038         normalized_interfaces.append(i)
00039     return interface.directlyProvides(obj, *normalized_interfaces)
00040 
00041 def classImplements(class_, *interfaces):
00042     # convert any Zope 2 interfaces to Zope 3 using fromZ2Interface
00043     normalized_interfaces = []
00044     for i in interfaces:
00045         try:
00046             i = fromZ2Interface(i)
00047         except ValueError: # already a Zope 3 interface
00048             pass
00049         normalized_interfaces.append(i)
00050     return interface.classImplements(class_, *normalized_interfaces)
00051 
00052 # postonly protection
00053 try:
00054     # Zope 2.8.9, 2.9.7 and 2.10.3 (and up)
00055     from AccessControl.requestmethod import postonly
00056 except ImportError:
00057     try:
00058         # Try the hotfix too
00059         from Products.Hotfix_20070320 import postonly
00060     except:
00061         def postonly(callable): return callable
00062 
00063 
00064 product_dir = package_home( globals() )
00065 product_prefix = os.path.join( os.path.split(product_dir)[:-1] )
00066 
00067 _wwwdir = os.path.join( product_dir, 'www' )
00068 
00069 #
00070 #   Most of this module is shamelessly ripped off from Zope3.test
00071 #
00072 def remove_stale_bytecode( arg, dirname, names ):
00073     """
00074         Troll product, removing compiled turds whose source is now gone.
00075     """
00076     names = map( os.path.normcase, names )
00077 
00078     for name in names:
00079 
00080         if name.endswith( ".pyc" ) or name.endswith( ".pyo" ):
00081 
00082             srcname = name[:-1]
00083 
00084             if srcname not in names:
00085 
00086                 fullname = os.path.join( dirname, name )
00087 
00088                 if __debug__:
00089                     print "Removing stale bytecode file", fullname
00090 
00091                 os.unlink( fullname )
00092 
00093 class TestFileFinder:
00094 
00095     def __init__( self ):
00096         self.files = []
00097 
00098     def visit( self, prefix, dir, files ):
00099         """
00100             Visitor for os.path.walk:  accumulates filenamse of unittests.
00101         """
00102         #if dir[-5:] != "tests":
00103         #    return
00104 
00105         # ignore tests that aren't in packages
00106         if not "__init__.py" in files:
00107 
00108             if not files or files == ['CVS']:
00109                 return
00110 
00111             if 0 and __debug__: # XXX: don't care!
00112                 print "not a package", dir
00113 
00114             return
00115 
00116         for file in files:
00117 
00118             if file.startswith( prefix ) and file.endswith( ".py" ):
00119                 path = os.path.join(dir, file)
00120                 self.files.append(path)
00121 
00122 def find_unit_test_files( from_dir=product_dir, test_prefix='test' ):
00123     """
00124         Walk the product, return a list of all unittest files.
00125     """
00126     finder = TestFileFinder()
00127     os.path.walk( from_dir, finder.visit, test_prefix )
00128     return finder.files
00129 
00130 def module_name_from_path( path ):
00131     """
00132         Return the dotted module name matching the filesystem path.
00133     """
00134     assert path.endswith( '.py' )
00135     path = path[:-3]
00136     path = path[ len(product_prefix) + 1: ] # strip extraneous crap
00137     dirs = []
00138     while path:
00139         path, end = os.path.split( path )
00140         dirs.insert( 0, end )
00141     return ".".join( dirs )
00142 
00143 def get_suite( file ):
00144     """
00145         Retrieve a TestSuite from 'file'.
00146     """
00147     module_name = module_name_from_path( file )
00148     loader = unittest.defaultTestLoader
00149     try:
00150         suite = loader.loadTestsFromName( '%s.test_suite' % module_name )
00151     except AttributeError:
00152 
00153         try:
00154             suite = loader.loadTestsFromName(  module_name )
00155         except ImportError, err:
00156             print "Error importing %s\n%s" % (module_name, err)
00157             raise
00158     return suite
00159 
00160 def allTests( from_dir=product_dir, test_prefix='test' ):
00161     """
00162         Walk the product and build a unittest.TestSuite aggregating tests.
00163     """
00164     os.path.walk( from_dir, remove_stale_bytecode, None )
00165     test_files = find_unit_test_files( from_dir, test_prefix )
00166     test_files.sort()
00167 
00168     suite = unittest.TestSuite()
00169 
00170     for test_file in test_files:
00171 
00172         s = get_suite( test_file )
00173         if s is not None:
00174             suite.addTest( s )
00175 
00176     return suite
00177 
00178 
00179 def makestr(s):
00180     """Converts 's' to a non-Unicode string"""
00181     if isinstance(s, unicode):
00182         s = s.encode('utf-8')
00183     return str(s)
00184 
00185 def createViewName(method_name, user_handle=None):
00186     """
00187         Centralized place for creating the "View Name" that identifies
00188         a ZCacheable record in a RAMCacheManager
00189     """
00190     if not user_handle:
00191         return makestr(method_name)
00192     else:
00193         return '%s-%s' % (makestr(method_name), makestr(user_handle))
00194 
00195 def createKeywords(**kw):
00196     """
00197         Centralized place for creating the keywords that identify
00198         a ZCacheable record in a RAMCacheManager.
00199 
00200         Keywords are hashed so we don't accidentally expose sensitive
00201         information.
00202     """
00203     keywords = sha.new()
00204 
00205     items = kw.items()
00206     items.sort()
00207     for k, v in items:
00208         keywords.update(makestr(k))
00209         keywords.update(makestr(v))
00210 
00211     return {'keywords': keywords.hexdigest()}
00212