I finally cleaned up the code I've been using for a while now to grab
objects out of modules via dotted-package names (all this work to avoid
using exec! Sheesh!). Feel free to use it, abuse it, or comment on it. I
realize many of you already do this on your own--this is just sugar for
the newbies. I'm releasing/announcing it for three reasons:
1. The ego rush of authorship, :D
2. I continually hear people asking for similar (if not exact)
functionality, especially those coming from a Java/Tomcat background,
and
3. The name is cool. I spent a lot of time on it.
Here 'tis:
# xray.py
"""Load modules, classes, functions, and attributes by dotted package
names.
Usage:
desiredClass = xray.classes("m yapp.strtools.a lwayslowercase" , str)
newInstance = desiredClass()
or
for f in startup_functio n_names:
func_object = xray.functions( f)
func_object()
Rationale:
I try to create systems that are configurable by deployers; mostly
becase I
hate it when an application forces me to use the database, filesystem,
communication protocol, algorithm, or operating system du jour.
Abstracting
these basic components of an application is its own study (look up the
Gang
of Four "Strategy" pattern for a start); this is often accomplished with
classes which share signatures, often via subclassing. However, the
deployer
then needs to specify the class they wish to use. This module gives them
the ability to specify that with a single string (for example, in a text
configuration file).
"""
import sys
def modules(moduleP ath):
"""Load a module and retrieve a reference to that module."""
try:
aMod = sys.modules[modulePath]
if aMod is None:
raise KeyError
except KeyError:
# The last [''] is important.
aMod = __import__(modu lePath, globals(), locals(), [''])
sys.modules[modulePath] = aMod
return aMod
def attributes(full AttributeName):
"""Load a module and retrieve an attribute of that module."""
# Parse out the path, module, and attribute
lastDot = fullAttributeNa me.rfind(u".")
attrName = fullAttributeNa me[lastDot + 1:]
modPath = fullAttributeNa me[:lastDot]
aMod = modules(modPath )
# Let an AttributeError propagate outward.
anAttr = getattr(aMod, attrName)
# Return a reference to the attribute.
return anAttr
def functions(fullF uncName):
"""Load a module and retrieve a function object."""
aFunc = attributes(full FuncName)
# Assert that the function is a *callable* attribute.
if not callable(aFunc) :
raise TypeError(u"'%s ' is not callable." % fullFuncName)
# Return a reference to the function itself,
# not the results of the function.
return aFunc
def classes(fullCla ssName, parentClass=Non e):
"""Load a module and retrieve a class (NOT an instance).
If the parentClass is supplied, className must be of parentClass
or a subclass of parentClass (or None is returned).
"""
aClass = functions(fullC lassName)
# Assert that the class is a subclass of parentClass.
if parentClass is not None:
if not issubclass(aCla ss, parentClass):
raise TypeError(u"'%s ' is not a subclass of %s" %
(fullClassName, parentClass.__n ame__))
# Return a reference to the class itself, not an instantiated
object.
return aClass
# end xray.py
Robert Brewer
MIS
Amor Ministries
fumanchu@amor.o rg
objects out of modules via dotted-package names (all this work to avoid
using exec! Sheesh!). Feel free to use it, abuse it, or comment on it. I
realize many of you already do this on your own--this is just sugar for
the newbies. I'm releasing/announcing it for three reasons:
1. The ego rush of authorship, :D
2. I continually hear people asking for similar (if not exact)
functionality, especially those coming from a Java/Tomcat background,
and
3. The name is cool. I spent a lot of time on it.
Here 'tis:
# xray.py
"""Load modules, classes, functions, and attributes by dotted package
names.
Usage:
desiredClass = xray.classes("m yapp.strtools.a lwayslowercase" , str)
newInstance = desiredClass()
or
for f in startup_functio n_names:
func_object = xray.functions( f)
func_object()
Rationale:
I try to create systems that are configurable by deployers; mostly
becase I
hate it when an application forces me to use the database, filesystem,
communication protocol, algorithm, or operating system du jour.
Abstracting
these basic components of an application is its own study (look up the
Gang
of Four "Strategy" pattern for a start); this is often accomplished with
classes which share signatures, often via subclassing. However, the
deployer
then needs to specify the class they wish to use. This module gives them
the ability to specify that with a single string (for example, in a text
configuration file).
"""
import sys
def modules(moduleP ath):
"""Load a module and retrieve a reference to that module."""
try:
aMod = sys.modules[modulePath]
if aMod is None:
raise KeyError
except KeyError:
# The last [''] is important.
aMod = __import__(modu lePath, globals(), locals(), [''])
sys.modules[modulePath] = aMod
return aMod
def attributes(full AttributeName):
"""Load a module and retrieve an attribute of that module."""
# Parse out the path, module, and attribute
lastDot = fullAttributeNa me.rfind(u".")
attrName = fullAttributeNa me[lastDot + 1:]
modPath = fullAttributeNa me[:lastDot]
aMod = modules(modPath )
# Let an AttributeError propagate outward.
anAttr = getattr(aMod, attrName)
# Return a reference to the attribute.
return anAttr
def functions(fullF uncName):
"""Load a module and retrieve a function object."""
aFunc = attributes(full FuncName)
# Assert that the function is a *callable* attribute.
if not callable(aFunc) :
raise TypeError(u"'%s ' is not callable." % fullFuncName)
# Return a reference to the function itself,
# not the results of the function.
return aFunc
def classes(fullCla ssName, parentClass=Non e):
"""Load a module and retrieve a class (NOT an instance).
If the parentClass is supplied, className must be of parentClass
or a subclass of parentClass (or None is returned).
"""
aClass = functions(fullC lassName)
# Assert that the class is a subclass of parentClass.
if parentClass is not None:
if not issubclass(aCla ss, parentClass):
raise TypeError(u"'%s ' is not a subclass of %s" %
(fullClassName, parentClass.__n ame__))
# Return a reference to the class itself, not an instantiated
object.
return aClass
# end xray.py
Robert Brewer
MIS
Amor Ministries
fumanchu@amor.o rg