Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

root/branches/crazycache/dejavu/xray.py

Revision 479 (checked in by fumanchu, 1 year ago)

Moved all content down into the new dejavu top-level folder.

  • Property svn:eol-style set to native
Line 
1 """Load modules, classes, functions, and attributes by dotted package names.
2
3 This work, including the source code, documentation
4 and related data, is placed into the public domain.
5
6 The orginal author is Robert Brewer.
7
8 THIS SOFTWARE IS PROVIDED AS-IS, WITHOUT WARRANTY
9 OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
10 MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE
11 ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
12 RESULTING FROM THE USE, MODIFICATION, OR
13 REDISTRIBUTION OF THIS SOFTWARE.
14
15 Usage:
16
17     desiredClass = xray.classes("myapp.stringtools.alwayslowercase", str)
18     newInstance = desiredClass()
19
20 or
21
22     for f in startup_function_names:
23         func_object = xray.functions(f)
24         func_object()
25
26
27 Rationale:
28
29 I try to create systems that are configurable by deployers; mostly becase I
30 hate it when an application forces me to use the database, filesystem,
31 communication protocol, algorithm, or operating system du jour. Abstracting
32 these basic components of an application is its own study (look up the Gang
33 of Four "Strategy" pattern for a start); this is often accomplished with
34 classes which share signatures, often via subclassing. However, the deployer
35 then needs to specify the class they wish to use. This module gives them
36 the ability to specify that with a single string (for example, in a text
37 configuration file).
38
39 """
40
41 import sys
42
43 def modules(modulePath):
44     """Load a module and retrieve a reference to that module."""
45     try:
46         aMod = sys.modules[modulePath]
47         if aMod is None:
48             raise KeyError
49     except KeyError:
50         # The last [''] is important.
51         aMod = __import__(modulePath, globals(), locals(), [''])
52     return aMod
53
54 def attributes(fullAttributeName):
55     """Load a module and retrieve an attribute of that module."""
56    
57     # Parse out the path, module, and attribute
58     lastDot = fullAttributeName.rfind(u".")
59     attrName = fullAttributeName[lastDot + 1:]
60     modPath = fullAttributeName[:lastDot]
61    
62     aMod = modules(modPath)
63     # Let an AttributeError propagate outward.
64     try:
65         anAttr = getattr(aMod, attrName)
66     except AttributeError:
67         raise AttributeError("'%s' object has no attribute '%s'"
68                              % (modPath, attrName))
69    
70     # Return a reference to the attribute.
71     return anAttr
72
73 def functions(fullFuncName):
74     """Load a module and retrieve a function object."""
75    
76     aFunc = attributes(fullFuncName)
77    
78     # Assert that the function is a *callable* attribute.
79     if not callable(aFunc):
80         raise TypeError(u"'%s' is not callable." % fullFuncName)
81    
82     # Return a reference to the function itself,
83     # not the results of the function.
84     return aFunc
85
86 def classes(fullClassName, parentClass=None):
87     """Load a module and retrieve a class (NOT an instance).
88     
89     If the parentClass is supplied, className must be of parentClass
90     or a subclass of parentClass (or None is returned).
91     """
92     aClass = functions(fullClassName)
93    
94     # Assert that the class is a subclass of parentClass.
95     if parentClass is not None:
96         if not issubclass(aClass, parentClass):
97             raise TypeError(u"'%s' is not a subclass of %s" %
98                             (fullClassName, parentClass.__name__))
99    
100     # Return a reference to the class itself, not an instantiated object.
101     return aClass
102
Note: See TracBrowser for help on using the browser.