# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------
"""
Some useful functions to be used within the Modeling package, or by
tools using this framework.
The module also defines two classes:
- `base_object` is equivalent to ``object`` (``types.ObjectType``) when
it is available (python2.2 or higher), or is an empty class in python2.1
- `base_persistent_object` equals to ``ZODB.Persistent`` if ZODB is
installed, or else equals to `base_object`. This is for use by `Model`,
`Entity`, `Attribute` and `Relationship` --the ZModeler in particular
requires that they inherit from ``ZODB.Persistent`` so that they can be
stored in the zodb.
$Id: utils.py 980 2006-02-26 18:04:47Z sbigaret $"""
__version__='$Revision: 980 $'[11:-2]
__allow_access_to_unprotected_subobjects__=1
import types, string, sys
from time import strftime
import types
try:
base_object = types.ObjectType
newclass = 1
except AttributeError:
class base_object : pass
newclass = 0
try:
import ZODB
from Persistence import Persistent
base_persistent_object=Persistent
except:
base_persistent_object=base_object
_validFirstLetter = "_"+string.letters
def isaValidName(aName):
"Checks"
# i.e.: a string, length >=0, no '/' (separator for PersistentID!)
if not aName or type(aName) is not types.StringType: return 0
if aName[0] not in _validFirstLetter: return 0
if aName.find('/')!=-1: return 0
return 1
def capitalizeFirstLetter(aName):
"Return the same string with the first letter capitalized"
return aName[0].upper()+aName[1:]
def lower(aString):
"Return the same string w/ all letter lower"
return string.lower(aString)
def stringToPythonIdentifier(aString):
"""
Transforms a string to a valid python identifier, i.e. replaces all
spaces with underscores and drops all chars not in
(strings.)letters+digits+'_'
"""
elements=string.split(aString, ' ')
elements=[string.join(filter(lambda s: s in string.letters+string.digits+'_',
list(element)), '')
for element in elements]
return string.join(elements, '_')
def isListOrTuple(anObject):
"""
Returns true if 'anObject' is a sequence-like object, false otherwise
In this context, a sequence-like object is a tuple, a list, or an instance
of Modeling.FaultHandler.AccessArrayFaultHandler
"""
if type(anObject) is types.TupleType or type(anObject) is types.ListType:
return 1
from FaultHandler import AccessArrayFaultHandler
return isinstance(anObject, AccessArrayFaultHandler)
def toBoolean(param):
"""
If param is a string (or unicode) and equals to 0, returns 0 ; otherwise
returns 'not not param'.
"""
if type(param) in (types.StringType, types.UnicodeType):
if param=='0': return 0
return not not param
if sys.version_info < (2, 2):
class staticmethod: # Static method wrapper
def __init__(self, aMethod):
self._method=aMethod
def __call__(self, *args, **kw):
return self._method(*args, **kw)
else:
staticmethod=staticmethod
StaticMethod=staticmethod # backward compatibility
def eliminate_multiple_occurences(sequence, func=lambda a: a):
"""
Eliminates multiple occurences of items in 'sequence' and returns the
corresponding list. The returned list is a subset of the supplied sequence,
and the original order of items is preserved (if an item is present more
than once in 'sequence', only the first occurence is present in the returned
list).
Parameters:
sequence -- a sequence (list, tuple). The original sequence is left
untouched.
func -- optional parameter. Defaults to the identity function. You can
supply an other function to eliminate from the sequences all objects but
one whose 'func(object)' are equal.
"""
d={}; l=[]
for item in sequence:
if not d.get(func(item), None):
l.append(item)
d[func(item)]=item
return l
def getModule(name, path=None):
"""
Finds and load the module 'name'. This is used by method 'classForEntity()'.
Raises in case it cannot be found
See also: module 'imp', functions 'find_module()' and 'load_module()'
"""
from imp import find_module,load_module
file=None
try:
file, pathname, description=find_module(name, path)
zeModule=load_module(name, file, pathname, description)
return zeModule
finally:
if file:
file.close()
def finalize_docstrings(klass, aDict):
"""
Takes a class object and tries to update its docstring, as well as its
methods' docstrings, using the supplied dictionary.
This is used, for example, in Entity, where some docstrings contains
'%(key)s' statements, to be filled with the same thing ; this makes it
possible to update groups of methods / 'see also' paragraphs without having
to copy/paste things everywhere.
Parameters:
klass -- the class object whose docstrings should be updated
aDict -- the dictionary to use to update the docstrings.
"""
return
#try:
# klass.__doc__=klass.__doc__%aDict
#except TypeError:
# pass
#import inspect
#if inspect.isclass(klass):
# for n,m in inspect.getmembers(klass, inspect.ismethod):
# try:
# m.im_func.__doc__=m.__doc__%aDict
# except AttributeError: pass
# except TypeError: pass
def deprecated(methodName, replacement=None,removed_in_version=None):
msg="Method %s is deprecated."%methodName
if replacement:
msg+=" Please use %s instead."%replacement
if removed_in_version:
msg+="\nThis method will be removed for version %s"%removed_in_version
import warnings
warnings.warn(msg, DeprecationWarning, 3)
def cache_simple_methods(anInstance, exclude=None):
"""
Takes an instance object and caches the result for all simple methods,
i.e. methods that takes no arguments except 'self'. The caching is made by
substituting the method with a lambda returning the value the original
method returned.
This method does nothing under python v2.1 if ZODB is found in the path,
because it is incompatible with the extension class, used by classes Entity,
Relationship, etc.
Parameters:
anInstance -- the instance to examine
exclude -- a sequence of methods' names not to cache
See also: methods_to_cache()
"""
import os, sys
if not os.environ.get('MDL_ENABLE_SIMPLE_METHOD_CACHE', None):
return
if sys.version_info < (2,2):
import warnings
warnings.warn("Cannot cache methods on py2.1 when ZODB is in the python path", RuntimeWarning)
return
from new import instancemethod
for m in methods_to_cache(anInstance.__class__, exclude):
try:
res=m(anInstance)
except (NotImplementedError, 'Unimplemented', "Nonsense"):
continue
l=lambda self, res=res: res
cached_m=instancemethod(l, anInstance, anInstance.__class__)
setattr(anInstance, m.__name__, cached_m)
def methods_to_cache(aClass, exclude=None):
"""
Searches and returns within 'aClass' the methods that accepts no arguments
except 'self'.
Parameters:
aClass -- the class to examine
exclude -- a sequence of methods' names to exclude from the result set
"""
if exclude is None:
exclude=[]
import inspect
isfunction=inspect.isfunction
classDict=aClass.__dict__
methods=[(func, inspect.getargspec(func))
for func in classDict.values()
if isfunction(func) and func.__name__!='__init__']
methods=[m[0] for m in methods if len(m[1][0])==1]
methods=[m for m in methods if m.__name__ not in exclude]
return methods
def migration_warnings():
"""
This method is responsible for warning the user when we detect that he/she
is relying on a feature (e.g. an environment variable) that has been
deprecated/removed and as no effect anymore (or will have no effect anymore
in a near future).
"""
import os,warnings
if os.environ.has_key('MDL_PERMANENT_DB_CONNECTION'):
msg="Environment variable MDL_PERMANENT_DB_CONNECTION is deprecated since 0.9pre17 and it has no effect anymore. The framework's default behaviour is now to leave the database connection opened. This variable has been replaced by the variable MDL_TRANSIENT_DB_CONNECTION which has the inverse semantics. Please refer to the User's Guide, appendix Environment Variables, for further details"
warnings.warn(msg, DeprecationWarning)
|