Ñò ÐwHc @sÕdZddklZlZlZddklZddklZl Z l Z l Z l Z l Z lZlZlZlZlZddklZlZdddd d gZd „Zd efd „ƒYZdeefd„ƒYZdefd„ƒYZde efd„ƒYZde efd„ƒYZe eeƒe ee ƒe eeƒe eeƒe eeƒe eeƒddd„ZeeddƒZ eeddƒZ!eed ƒZ"eedƒZ#d„Z$dS(sò This module provides four decorators: ``prioritized_when`` ``prioritized_around`` ``prioritized_before`` ``prioritized_after`` These behave like their ``peak.rules`` counterparts except that they accept an optional ``prio`` argument which can be used to provide a comparable object (usually an integer) that will be used to disambiguate situations in which more than rule applies to the given arguments and no rule is more specific than another. That is, situations in which an ``peak.rules.AmbiguousMethods`` would have been raised. This is useful for libraries which want to be extensible via generic functions but want their users to easily override a method without figuring out how to write a more specific rule or when it is not feasible. For example, TurboJson provides a ``jsonify`` function that looks like this:: >>> def jsonify(obj): ... "jsonify an object" And extends it so it can handle SqlAlchemy mapped classes in a way similar to this one:: >>> from peak.rules import when >>> def jsonify_sa(obj): ... print "You're a SA object and I'm going to jsonify you!" >>> when(jsonify, "hasattr(obj, 'c')")(jsonify_sa) # doctest: +ELLIPSIS >>> class Person(object): ... def __init__(self): ... self.c = "im a stub" >>> jsonify(Person()) You're a SA object and I'm going to jsonify you! So far so good, however, when a user of the library wants to override the built in implementation it can become quite hard since they have to write a more specific rule which can be tedious, for example:: hasattr(self, 'c') and isinstance(obj, Person) Notice the ``hasattr`` test, even though ``isinstance(obj, Person)`` implies it, just to make it more specific than the built in, this gets more cumbersome the more complicated the expression becomes. Else this is what happens:: >>> def jsonify_Person(obj): ... print "No way, I'm going to jsonify you!" >>> when(jsonify, (Person,))(jsonify_Person) # doctest: +ELLIPSIS >>> try: ... jsonify(Person()) ... except AmbiguousMethods: ... print "I told you, gfs can sometimes be a pain" I told you, gfs can sometimes be a pain To remedy this situation ``prioritized_when`` can be used to provide an implementation that will override the one declared with ``when``:: >>> def jsonify_Person2(obj): ... print "No way, I'm going to jsonify you!" >>> prioritized_when(jsonify, (Person,))(jsonify_Person2) # doctest: +ELLIPSIS >>> jsonify(Person()) No way, I'm going to jsonify you! Notice that we didn't need a ``prio`` argument. This is because methods decorated with ``prioritized_when`` always override those that have been decorated with ``peak.rules.when``. Methods decorated with ``prioritized_when`` can also override other methods that have been decorated by the same decorator using the ``prio`` parameter, the one which compares greater wins, if both are equal ``AmbiguousMethods`` will be raised as usual. >>> def jsonify_Person3(obj): ... print "Don't be so smart, I am, my prio is higher!" >>> prioritized_when(jsonify, (Person,), prio=1)(jsonify_Person3) # doctest: +ELLIPSIS >>> jsonify(Person()) Don't be so smart, I am, my prio is higher! For convenience, a ``generic`` decorator is provided too which behaves like ``peak.rules.dispatch.generic`` except that the ``when``,...,``after`` decorators that will be bound as attributes of the decorated function will be prioritized:: >>> @generic ... def f(n): pass >>> f(5) Traceback (most recent call last): ... NoApplicableMethods: ((5,), {}) Add a default rule:: >>> @f.when() ... def default_f(n): ... return n >>> f(5) 5 Add a default rule that overrides the former:: >>> @f.when(prio=1) ... def new_default_f(n): ... return n+1 >>> f(5) 6 iÿÿÿÿ(tdecorate_assignmentt frameinfotdecorate_class(t with_name( tMethodtAroundtBeforetAftertabstracttalways_overridestAmbiguousMethodst Dispatchingt rules_fort parse_ruletcombine_actions(tclone_functiont ParseContexttprioritized_whentprioritized_aroundtprioritized_aftertprioritized_beforeRcCs(t|tƒodSt|iddƒS(Niayþÿtprioi(t isinstanceR tgetattrtbody(tobj((s7/usr/lib/python2.6/site-packages/prioritized_methods.pyt _get_prio‘stPrioritizedMixincBseZd„ZRS(cCs”t|ƒ}t|ƒ}||jo)|io|it|i|ƒƒS|S||jo)|io|it|i|ƒƒS|St||gƒS(s× Merge with other Methods giving priority to the one with the highest ``prio`` attribute in the Method's body. If both priorities are equal return :exc:`peak.rules.AmbiguousMethods` (Rtcan_tailt tail_withRttailR (tselftothertmy_priot other_prio((s7/usr/lib/python2.6/site-packages/prioritized_methods.pytmerge™s      (t__name__t __module__R#(((s7/usr/lib/python2.6/site-packages/prioritized_methods.pyR˜stPrioritizedMethodcBseZdZRS(sº A :class:`peak.rules.Method` subclass that will merge ambiguous methods giving preference to the one that has the ``prio`` attribute in it's body that compares greater. (R$R%t__doc__(((s7/usr/lib/python2.6/site-packages/prioritized_methods.pyR&¬stPrioritizedAroundcBseZdZRS(sq A :class:`PrioritizedMethod` subclass that has preference over any other :class:`peak.rules.Method` (R$R%R'(((s7/usr/lib/python2.6/site-packages/prioritized_methods.pyR(³stPrioritizedBeforecBseZdZRS(s3Method(s) to be called before the primary method(s)(R$R%R'(((s7/usr/lib/python2.6/site-packages/prioritized_methods.pyR)¹stPrioritizedAftercBseZdZRS(s2Method(s) to be called after the primary method(s)(R$R%R'(((s7/usr/lib/python2.6/site-packages/prioritized_methods.pyR*½sicsu|djod|i}n|tjo d‰n |i‰ddd|‡fd†}t||ƒ}||_|S(Ns6Extend a generic function with a method of type ``%s``ics+‡‡‡‡‡fd†}t||ˆƒS(Nc sØ|}t|ƒ}ˆ|_ˆp|}tˆƒ‰tˆƒi‰t|ƒ\}}}} t|ˆ|| ƒ‰‡‡‡‡fd†} |djot| d|ƒn | dƒ|i |ƒˆˆfjoˆS|S(Ncs ˆitˆˆˆ|ƒƒ|S(N(taddR (tcls(tenginetrulestpredtcontext(s7/usr/lib/python2.6/site-packages/prioritized_methods.pytregister_for_classãstclasstframe( RRR R R-RRRtNonetget( tcb_frametnametfunct old_localst orig_funct real_frametkindtmoduletlocals_tglobals_R1(RR3R/tftmaker(R-R.R0s7/usr/lib/python2.6/site-packages/prioritized_methods.pytcallbackØs      (R(R@R/tdepthR3RRB(RA(RR@R/R3s7/usr/lib/python2.6/site-packages/prioritized_methods.pytdecorate×s((R4R$RtmakeRR'(R,R7tdoct default_prioRD((RAs7/usr/lib/python2.6/site-packages/prioritized_methods.pytmake_decoratorÏs     sô Extend a generic function with a new action. Optional parameter ``prio`` can be used to prioritize the new action in case adding it causes an :exc:`peak.rules.AmbiguousMethod` exception when the generic function is called. s? Extend a generic function with a new action. This action will be executed before any action registered with ``prioritized_when``. Optional parameter ``prio`` can be used to prioritize the new action in case adding it causes an ``AmbiguousMethod`` exception when the generic function is called. cCsRti|ƒ|_ti|ƒ|_ti|ƒ|_ti|ƒ|_t |ƒS(s¦ Convenience decorator to bind ``when``, ``around``, ``after`` and ``before`` decorators to the decorated function and declareing it as ``abstract``. ( Rt__get__twhenRtaroundRtbeforeRtafterR(R8((s7/usr/lib/python2.6/site-packages/prioritized_methods.pytgenerics N(%R'tpeak.util.decoratorsRRRtpeak.util.assemblerRt peak.rulesRRRRRR R R R R Rtpeak.rules.coreRRt__all__RtobjectRR&R(R)R*R4RHRRRRRN(((s7/usr/lib/python2.6/site-packages/prioritized_methods.pytƒs<L         +