Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: third_party/twisted_8_1/twisted/python/reflect.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_reflect -*-
2
3 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6
7 """
8 Standardized versions of various cool and/or strange things that you can do
9 with Python's reflection capabilities.
10 """
11
12 from __future__ import nested_scopes
13
14
15 # System Imports
16 import sys
17 import os
18 import types
19 import string
20 import pickle
21 import new
22 import traceback
23 import weakref
24 import re
25 import warnings
26 try:
27 from collections import deque
28 except ImportError:
29 deque = list
30
31 RegexType = type(re.compile(""))
32
33
34 try:
35 import cStringIO as StringIO
36 except ImportError:
37 import StringIO
38
39 class Settable:
40 """
41 A mixin class for syntactic sugar. Lets you assign attributes by
42 calling with keyword arguments; for example, C{x(a=b,c=d,y=z)} is the
43 same as C{x.a=b;x.c=d;x.y=z}. The most useful place for this is
44 where you don't want to name a variable, but you do want to set
45 some attributes; for example, C{X()(y=z,a=b)}.
46 """
47 def __init__(self, **kw):
48 self(**kw)
49
50 def __call__(self,**kw):
51 for key,val in kw.items():
52 setattr(self,key,val)
53 return self
54
55
56 class AccessorType(type):
57 """Metaclass that generates properties automatically.
58
59 This is for Python 2.2 and up.
60
61 Using this metaclass for your class will give you explicit accessor
62 methods; a method called set_foo, will automatically create a property
63 'foo' that uses set_foo as a setter method. Same for get_foo and del_foo.
64
65 Note that this will only work on methods that are present on class
66 creation. If you add methods after the class is defined they will not
67 automatically become properties. Likewise, class attributes will only
68 be used if they are present upon class creation, and no getter function
69 was set - if a getter is present, the class attribute will be ignored.
70
71 This is a 2.2-only alternative to the Accessor mixin - just set in your
72 class definition::
73
74 __metaclass__ = AccessorType
75
76 """
77
78 def __init__(self, name, bases, d):
79 type.__init__(self, name, bases, d)
80 accessors = {}
81 prefixs = ["get_", "set_", "del_"]
82 for k in d.keys():
83 v = getattr(self, k)
84 for i in range(3):
85 if k.startswith(prefixs[i]):
86 accessors.setdefault(k[4:], [None, None, None])[i] = v
87 for name, (getter, setter, deler) in accessors.items():
88 # create default behaviours for the property - if we leave
89 # the getter as None we won't be able to getattr, etc..
90 if getter is None:
91 if hasattr(self, name):
92 value = getattr(self, name)
93 def getter(this, value=value, name=name):
94 if this.__dict__.has_key(name):
95 return this.__dict__[name]
96 else:
97 return value
98 else:
99 def getter(this, name=name):
100 if this.__dict__.has_key(name):
101 return this.__dict__[name]
102 else:
103 raise AttributeError, "no such attribute %r" % name
104 if setter is None:
105 def setter(this, value, name=name):
106 this.__dict__[name] = value
107 if deler is None:
108 def deler(this, name=name):
109 del this.__dict__[name]
110 setattr(self, name, property(getter, setter, deler, ""))
111
112
113 class PropertyAccessor(object):
114 """A mixin class for Python 2.2 that uses AccessorType.
115
116 This provides compatability with the pre-2.2 Accessor mixin, up
117 to a point.
118
119 Extending this class will give you explicit accessor methods; a
120 method called set_foo, for example, is the same as an if statement
121 in __setattr__ looking for 'foo'. Same for get_foo and del_foo.
122
123 There are also reallyDel and reallySet methods, so you can
124 override specifics in subclasses without clobbering __setattr__
125 and __getattr__, or using non-2.1 compatible code.
126
127 There is are incompatibilities with Accessor - accessor
128 methods added after class creation will *not* be detected. OTOH,
129 this method is probably way faster.
130
131 In addition, class attributes will only be used if no getter
132 was defined, and instance attributes will not override getter methods
133 whereas in original Accessor the class attribute or instance attribute
134 would override the getter method.
135 """
136 # addendum to above:
137 # The behaviour of Accessor is wrong IMHO, and I've found bugs
138 # caused by it.
139 # -- itamar
140
141 __metaclass__ = AccessorType
142
143 def reallySet(self, k, v):
144 self.__dict__[k] = v
145
146 def reallyDel(self, k):
147 del self.__dict__[k]
148
149
150 class Accessor:
151 """
152 Extending this class will give you explicit accessor methods; a
153 method called C{set_foo}, for example, is the same as an if statement
154 in L{__setattr__} looking for C{'foo'}. Same for C{get_foo} and
155 C{del_foo}. There are also L{reallyDel} and L{reallySet} methods,
156 so you can override specifics in subclasses without clobbering
157 L{__setattr__} and L{__getattr__}.
158
159 This implementation is for Python 2.1.
160 """
161
162 def __setattr__(self, k,v):
163 kstring='set_%s'%k
164 if hasattr(self.__class__,kstring):
165 return getattr(self,kstring)(v)
166 else:
167 self.reallySet(k,v)
168
169 def __getattr__(self, k):
170 kstring='get_%s'%k
171 if hasattr(self.__class__,kstring):
172 return getattr(self,kstring)()
173 raise AttributeError("%s instance has no accessor for: %s" % (qual(self. __class__),k))
174
175 def __delattr__(self, k):
176 kstring='del_%s'%k
177 if hasattr(self.__class__,kstring):
178 getattr(self,kstring)()
179 return
180 self.reallyDel(k)
181
182 def reallySet(self, k,v):
183 """
184 *actually* set self.k to v without incurring side-effects.
185 This is a hook to be overridden by subclasses.
186 """
187 if k == "__dict__":
188 self.__dict__.clear()
189 self.__dict__.update(v)
190 else:
191 self.__dict__[k]=v
192
193 def reallyDel(self, k):
194 """
195 *actually* del self.k without incurring side-effects. This is a
196 hook to be overridden by subclasses.
197 """
198 del self.__dict__[k]
199
200 # just in case
201 OriginalAccessor = Accessor
202
203
204 class Summer(Accessor):
205 """
206 Extend from this class to get the capability to maintain 'related
207 sums'. Have a tuple in your class like the following::
208
209 sums=(('amount','credit','credit_total'),
210 ('amount','debit','debit_total'))
211
212 and the 'credit_total' member of the 'credit' member of self will
213 always be incremented when the 'amount' member of self is
214 incremented, similiarly for the debit versions.
215 """
216
217 def reallySet(self, k,v):
218 "This method does the work."
219 for sum in self.sums:
220 attr=sum[0]
221 obj=sum[1]
222 objattr=sum[2]
223 if k == attr:
224 try:
225 oldval=getattr(self, attr)
226 except:
227 oldval=0
228 diff=v-oldval
229 if hasattr(self, obj):
230 ob=getattr(self,obj)
231 if ob is not None:
232 try:oldobjval=getattr(ob, objattr)
233 except:oldobjval=0.0
234 setattr(ob,objattr,oldobjval+diff)
235
236 elif k == obj:
237 if hasattr(self, attr):
238 x=getattr(self,attr)
239 setattr(self,attr,0)
240 y=getattr(self,k)
241 Accessor.reallySet(self,k,v)
242 setattr(self,attr,x)
243 Accessor.reallySet(self,y,v)
244 Accessor.reallySet(self,k,v)
245
246 class QueueMethod:
247 """ I represent a method that doesn't exist yet."""
248 def __init__(self, name, calls):
249 self.name = name
250 self.calls = calls
251 def __call__(self, *args):
252 self.calls.append((self.name, args))
253
254
255 def funcinfo(function):
256 """
257 this is more documentation for myself than useful code.
258 """
259 warnings.warn(
260 "[v2.5] Use inspect.getargspec instead of twisted.python.reflect.funcinf o",
261 DeprecationWarning,
262 stacklevel=2)
263 code=function.func_code
264 name=function.func_name
265 argc=code.co_argcount
266 argv=code.co_varnames[:argc]
267 defaults=function.func_defaults
268
269 out = []
270
271 out.append('The function %s accepts %s arguments' % (name ,argc))
272 if defaults:
273 required=argc-len(defaults)
274 out.append('It requires %s arguments' % required)
275 out.append('The arguments required are: %s' % argv[:required])
276 out.append('additional arguments are:')
277 for i in range(argc-required):
278 j=i+required
279 out.append('%s which has a default of' % (argv[j], defaults[i]))
280 return out
281
282
283 ISNT=0
284 WAS=1
285 IS=2
286
287
288 def fullFuncName(func):
289 qualName = (str(pickle.whichmodule(func, func.__name__)) + '.' + func.__name __)
290 if namedObject(qualName) is not func:
291 raise Exception("Couldn't find %s as %s." % (func, qualName))
292 return qualName
293
294 def qual(clazz):
295 """Return full import path of a class."""
296 return clazz.__module__ + '.' + clazz.__name__
297
298 def getcurrent(clazz):
299 assert type(clazz) == types.ClassType, 'must be a class...'
300 module = namedModule(clazz.__module__)
301 currclass = getattr(module, clazz.__name__, None)
302 if currclass is None:
303 return clazz
304 return currclass
305
306 def getClass(obj):
307 """Return the class or type of object 'obj'.
308 Returns sensible result for oldstyle and newstyle instances and types."""
309 if hasattr(obj, '__class__'):
310 return obj.__class__
311 else:
312 return type(obj)
313
314 # class graph nonsense
315
316 # I should really have a better name for this...
317 def isinst(inst,clazz):
318 if type(inst) != types.InstanceType or type(clazz)!= types.ClassType:
319 return isinstance(inst,clazz)
320 cl = inst.__class__
321 cl2 = getcurrent(cl)
322 clazz = getcurrent(clazz)
323 if issubclass(cl2,clazz):
324 if cl == cl2:
325 return WAS
326 else:
327 inst.__class__ = cl2
328 return IS
329 else:
330 return ISNT
331
332
333 def namedModule(name):
334 """Return a module given its name."""
335 topLevel = __import__(name)
336 packages = name.split(".")[1:]
337 m = topLevel
338 for p in packages:
339 m = getattr(m, p)
340 return m
341
342
343 def namedObject(name):
344 """Get a fully named module-global object.
345 """
346 classSplit = string.split(name, '.')
347 module = namedModule(string.join(classSplit[:-1], '.'))
348 return getattr(module, classSplit[-1])
349
350 namedClass = namedObject # backwards compat
351
352
353
354 class _NoModuleFound(Exception):
355 """
356 No module was found because none exists.
357 """
358
359
360
361 def _importAndCheckStack(importName):
362 """
363 Import the given name as a module, then walk the stack to determine whether
364 the failure was the module not existing, or some code in the module (for
365 example a dependent import) failing. This can be helpful to determine
366 whether any actual application code was run. For example, to distiguish
367 administrative error (entering the wrong module name), from programmer
368 error (writing buggy code in a module that fails to import).
369
370 @raise Exception: if something bad happens. This can be any type of
371 exception, since nobody knows what loading some arbitrary code might do.
372
373 @raise _NoModuleFound: if no module was found.
374 """
375 try:
376 try:
377 return __import__(importName)
378 except ImportError:
379 excType, excValue, excTraceback = sys.exc_info()
380 while excTraceback:
381 execName = excTraceback.tb_frame.f_globals["__name__"]
382 if (execName is None or # python 2.4+, post-cleanup
383 execName == importName): # python 2.3, no cleanup
384 raise excType, excValue, excTraceback
385 excTraceback = excTraceback.tb_next
386 raise _NoModuleFound()
387 except:
388 # Necessary for cleaning up modules in 2.3.
389 sys.modules.pop(importName, None)
390 raise
391
392
393
394 def namedAny(name):
395 """
396 Retrieve a Python object from the global Python module namespace, by its
397 fully qualified name. The first part of the name, that describes a module,
398 will be discovered and imported.
399
400 @param name: the fully qualified name of a Python object, which is a
401 dot-separated list of python objects accessible via a name. This includes
402 packages, modules, and any Python object which has attributes. For
403 example, a fully-qualified name of this object is
404 'twisted.python.reflect.namedAny'.
405
406 @type name: L{str}
407
408 @return: the Python object identified by 'name'.
409
410 @raise ValueError: if the top level dotted name that is passed is not a
411 valid Python identifier, or the top level dotted name that is passed is not
412 a valid python module.
413
414 @raise AttributeError: if an attribute of an object along the way cannot be
415 accessed, or a module along the way is not found.
416
417 @raise ImportError: if any module involved cannot be imported for some
418 reason.
419 """
420 names = name.split('.')
421 topLevelPackage = None
422 moduleNames = names[:]
423 while not topLevelPackage:
424 trialname = '.'.join(moduleNames)
425 try:
426 topLevelPackage = _importAndCheckStack(trialname)
427 except _NoModuleFound:
428 moduleNames.pop()
429
430 obj = topLevelPackage
431 for n in names[1:]:
432 obj = getattr(obj, n)
433
434 return obj
435
436 def _reclass(clazz):
437 clazz = getattr(namedModule(clazz.__module__),clazz.__name__)
438 clazz.__bases__ = tuple(map(_reclass, clazz.__bases__))
439 return clazz
440
441
442
443
444 def macro(name, filename, source, **identifiers):
445 """macro(name, source, **identifiers)
446
447 This allows you to create macro-like behaviors in python. See
448 twisted.python.hook for an example of its usage.
449 """
450 if not identifiers.has_key('name'):
451 identifiers['name'] = name
452 source = source % identifiers
453 codeplace = "<%s (macro)>" % filename
454 code = compile(source, codeplace, 'exec')
455
456 # shield your eyes!
457 sm = sys.modules
458 tprm = "twisted.python.reflect.macros"
459 if not sm.has_key(tprm):
460 macros = new.module(tprm)
461 sm[tprm] = macros
462 macros.count = 0
463 macros = sm[tprm]
464 macros.count += 1
465 macroname = 'macro_' + str(macros.count)
466 tprmm = tprm + '.' + macroname
467 mymod = new.module(tprmm)
468 sys.modules[tprmm] = mymod
469 setattr(macros, macroname, mymod)
470 dict = mymod.__dict__
471
472 # Before we go on, I guess I should explain why I just did that. Basically
473 # it's a gross hack to get epydoc to work right, but the general idea is
474 # that it will be a useful aid in debugging in _any_ app which expects
475 # sys.modules to have the same globals as some function. For example, it
476 # would be useful if you were foolishly trying to pickle a wrapped function
477 # directly from a class that had been hooked.
478
479 exec code in dict, dict
480 return dict[name]
481
482 def _determineClass(x):
483 try:
484 return x.__class__
485 except:
486 return type(x)
487
488 def _determineClassName(x):
489 c = _determineClass(x)
490 try:
491 return c.__name__
492 except:
493 try:
494 return str(c)
495 except:
496 return '<BROKEN CLASS AT %s>' % id(c)
497
498 def safe_repr(o):
499 """safe_repr(anything) -> string
500
501 Returns a string representation of an object, or a string containing a
502 traceback, if that object's __repr__ raised an exception.
503 """
504
505 try:
506 return repr(o)
507 except:
508 io = StringIO.StringIO()
509 traceback.print_stack(file=io)
510 whati = _determineClassName(o)
511 swron = io.getvalue()
512 gwith = id(o)
513 you ='<%s instance at %s with repr error %s>' % (
514 whati,swron,gwith)
515 return you
516
517 def safe_str(o):
518 """safe_str(anything) -> string
519
520 Returns a string representation of an object, or a string containing a
521 traceback, if that object's __str__ raised an exception.
522 """
523
524 try:
525 return str(o)
526 except:
527 strExc = '\n'.join(traceback.format_exception(*sys.exc_info()))
528 clsName = _determineClassName(o)
529 obId = id(o)
530 return '<%s instance at %s with str error %s>' % (
531 clsName, obId, strExc)
532
533
534 ##the following were factored out of usage
535
536 def allYourBase(classObj, baseClass=None):
537 """allYourBase(classObj, baseClass=None) -> list of all base
538 classes that are subclasses of baseClass, unless it is None,
539 in which case all bases will be added.
540 """
541 l = []
542 accumulateBases(classObj, l, baseClass)
543 return l
544
545
546 def accumulateBases(classObj, l, baseClass=None):
547 for base in classObj.__bases__:
548 if baseClass is None or issubclass(base, baseClass):
549 l.append(base)
550 accumulateBases(base, l, baseClass)
551
552
553 def prefixedMethodNames(classObj, prefix):
554 """A list of method names with a given prefix in a given class.
555 """
556 dct = {}
557 addMethodNamesToDict(classObj, dct, prefix)
558 return dct.keys()
559
560
561 def addMethodNamesToDict(classObj, dict, prefix, baseClass=None):
562 """
563 addMethodNamesToDict(classObj, dict, prefix, baseClass=None) -> dict
564 this goes through 'classObj' (and its bases) and puts method names
565 starting with 'prefix' in 'dict' with a value of 1. if baseClass isn't
566 None, methods will only be added if classObj is-a baseClass
567
568 If the class in question has the methods 'prefix_methodname' and
569 'prefix_methodname2', the resulting dict should look something like:
570 {"methodname": 1, "methodname2": 1}.
571 """
572 for base in classObj.__bases__:
573 addMethodNamesToDict(base, dict, prefix, baseClass)
574
575 if baseClass is None or baseClass in classObj.__bases__:
576 for name, method in classObj.__dict__.items():
577 optName = name[len(prefix):]
578 if ((type(method) is types.FunctionType)
579 and (name[:len(prefix)] == prefix)
580 and (len(optName))):
581 dict[optName] = 1
582
583 def prefixedMethods(obj, prefix=''):
584 """A list of methods with a given prefix on a given instance.
585 """
586 dct = {}
587 accumulateMethods(obj, dct, prefix)
588 return dct.values()
589
590 def accumulateMethods(obj, dict, prefix='', curClass=None):
591 """accumulateMethods(instance, dict, prefix)
592 I recurse through the bases of instance.__class__, and add methods
593 beginning with 'prefix' to 'dict', in the form of
594 {'methodname':*instance*method_object}.
595 """
596 if not curClass:
597 curClass = obj.__class__
598 for base in curClass.__bases__:
599 accumulateMethods(obj, dict, prefix, base)
600
601 for name, method in curClass.__dict__.items():
602 optName = name[len(prefix):]
603 if ((type(method) is types.FunctionType)
604 and (name[:len(prefix)] == prefix)
605 and (len(optName))):
606 dict[optName] = getattr(obj, name)
607
608 def accumulateClassDict(classObj, attr, adict, baseClass=None):
609 """Accumulate all attributes of a given name in a class heirarchy into a sin gle dictionary.
610
611 Assuming all class attributes of this name are dictionaries.
612 If any of the dictionaries being accumulated have the same key, the
613 one highest in the class heirarchy wins.
614 (XXX: If \"higest\" means \"closest to the starting class\".)
615
616 Ex::
617
618 | class Soy:
619 | properties = {\"taste\": \"bland\"}
620 |
621 | class Plant:
622 | properties = {\"colour\": \"green\"}
623 |
624 | class Seaweed(Plant):
625 | pass
626 |
627 | class Lunch(Soy, Seaweed):
628 | properties = {\"vegan\": 1 }
629 |
630 | dct = {}
631 |
632 | accumulateClassDict(Lunch, \"properties\", dct)
633 |
634 | print dct
635
636 {\"taste\": \"bland\", \"colour\": \"green\", \"vegan\": 1}
637 """
638 for base in classObj.__bases__:
639 accumulateClassDict(base, attr, adict)
640 if baseClass is None or baseClass in classObj.__bases__:
641 adict.update(classObj.__dict__.get(attr, {}))
642
643
644 def accumulateClassList(classObj, attr, listObj, baseClass=None):
645 """Accumulate all attributes of a given name in a class heirarchy into a sin gle list.
646
647 Assuming all class attributes of this name are lists.
648 """
649 for base in classObj.__bases__:
650 accumulateClassList(base, attr, listObj)
651 if baseClass is None or baseClass in classObj.__bases__:
652 listObj.extend(classObj.__dict__.get(attr, []))
653
654
655 def isSame(a, b):
656 return (a is b)
657
658 def isLike(a, b):
659 return (a == b)
660
661 def modgrep(goal):
662 return objgrep(sys.modules, goal, isLike, 'sys.modules')
663
664 def isOfType(start, goal):
665 return ((type(start) is goal) or
666 (isinstance(start, types.InstanceType) and
667 start.__class__ is goal))
668
669
670 def findInstances(start, t):
671 return objgrep(start, t, isOfType)
672
673 def objgrep(start, goal, eq=isLike, path='', paths=None, seen=None, showUnknowns =0, maxDepth=None):
674 '''An insanely CPU-intensive process for finding stuff.
675 '''
676 if paths is None:
677 paths = []
678 if seen is None:
679 seen = {}
680 if eq(start, goal):
681 paths.append(path)
682 if seen.has_key(id(start)):
683 if seen[id(start)] is start:
684 return
685 if maxDepth is not None:
686 if maxDepth == 0:
687 return
688 maxDepth -= 1
689 seen[id(start)] = start
690 if isinstance(start, types.DictionaryType):
691 r = []
692 for k, v in start.items():
693 objgrep(k, goal, eq, path+'{'+repr(v)+'}', paths, seen, showUnknowns , maxDepth)
694 objgrep(v, goal, eq, path+'['+repr(k)+']', paths, seen, showUnknowns , maxDepth)
695 elif isinstance(start, (list, tuple, deque)):
696 for idx in xrange(len(start)):
697 objgrep(start[idx], goal, eq, path+'['+str(idx)+']', paths, seen, sh owUnknowns, maxDepth)
698 elif isinstance(start, types.MethodType):
699 objgrep(start.im_self, goal, eq, path+'.im_self', paths, seen, showUnkno wns, maxDepth)
700 objgrep(start.im_func, goal, eq, path+'.im_func', paths, seen, showUnkno wns, maxDepth)
701 objgrep(start.im_class, goal, eq, path+'.im_class', paths, seen, showUnk nowns, maxDepth)
702 elif hasattr(start, '__dict__'):
703 for k, v in start.__dict__.items():
704 objgrep(v, goal, eq, path+'.'+k, paths, seen, showUnknowns, maxDepth )
705 if isinstance(start, types.InstanceType):
706 objgrep(start.__class__, goal, eq, path+'.__class__', paths, seen, s howUnknowns, maxDepth)
707 elif isinstance(start, weakref.ReferenceType):
708 objgrep(start(), goal, eq, path+'()', paths, seen, showUnknowns, maxDept h)
709 elif (isinstance(start, types.StringTypes+
710 (types.IntType, types.FunctionType,
711 types.BuiltinMethodType, RegexType, types.FloatType,
712 types.NoneType, types.FileType)) or
713 type(start).__name__ in ('wrapper_descriptor', 'method_descriptor',
714 'member_descriptor', 'getset_descriptor')):
715 pass
716 elif showUnknowns:
717 print 'unknown type', type(start), start
718 return paths
719
720
721 def filenameToModuleName(fn):
722 """
723 Convert a name in the filesystem to the name of the Python module it is.
724
725 This is agressive about getting a module name back from a file; it will
726 always return a string. Agressive means 'sometimes wrong'; it won't look
727 at the Python path or try to do any error checking: don't use this method
728 unless you already know that the filename you're talking about is a Python
729 module.
730 """
731 fullName = os.path.abspath(fn)
732 base = os.path.basename(fn)
733 if not base:
734 # this happens when fn ends with a path separator, just skit it
735 base = os.path.basename(fn[:-1])
736 modName = os.path.splitext(base)[0]
737 while 1:
738 fullName = os.path.dirname(fullName)
739 if os.path.exists(os.path.join(fullName, "__init__.py")):
740 modName = "%s.%s" % (os.path.basename(fullName), modName)
741 else:
742 break
743 return modName
744
745 #boo python
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/python/rebuild.py ('k') | third_party/twisted_8_1/twisted/python/release.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698