ó \Z-Lc@s–dZddZddlmZddlZeZeZdddd d d d gZ e ej d ƒs~e ej d d„ƒnde fd„ƒYZd„Zd„Zd„Zd„Zd„Zed„Zed„Zed„Zdd„Zedd„Zedd„Zd„Zy8ddlmZmZmZmZmZmZeZWn eZnXdd!d„ƒYZd„Ze d kr’eƒndS("s„This module supports Cheetah's optional NameMapper syntax. Overview ================================================================================ NameMapper provides a simple syntax for accessing Python data structures, functions, and methods from Cheetah. It's called NameMapper because it 'maps' simple 'names' in Cheetah templates to possibly more complex syntax in Python. Its purpose is to make working with Cheetah easy for non-programmers. Specifically, non-programmers using Cheetah should NOT need to be taught (a) what the difference is between an object and a dictionary, (b) what functions and methods are, and (c) what 'self' is. A further aim (d) is to buffer the code in Cheetah templates from changes in the implementation of the Python data structures behind them. Consider this scenario: You are building a customer information system. The designers with you want to use information from your system on the client's website --AND-- they want to understand the display code and so they can maintian it themselves. You write a UI class with a 'customers' method that returns a dictionary of all the customer objects. Each customer object has an 'address' method that returns the a dictionary with information about the customer's address. The designers want to be able to access that information. Using PSP, the display code for the website would look something like the following, assuming your servlet subclasses the class you created for managing customer information: <%= self.customer()[ID].address()['city'] %> (42 chars) Using Cheetah's NameMapper syntax it could be any of the following: $self.customers()[$ID].address()['city'] (39 chars) --OR-- $customers()[$ID].address()['city'] --OR-- $customers()[$ID].address().city --OR-- $customers()[$ID].address.city --OR-- $customers()[$ID].address.city --OR-- $customers[$ID].address.city (27 chars) Which of these would you prefer to explain to the designers, who have no programming experience? The last form is 15 characters shorter than the PSP and, conceptually, is far more accessible. With PHP or ASP, the code would be even messier than the PSP This is a rather extreme example and, of course, you could also just implement '$getCustomer($ID).city' and obey the Law of Demeter (search Google for more on that). But good object orientated design isn't the point here. Details ================================================================================ The parenthesized letters below correspond to the aims in the second paragraph. DICTIONARY ACCESS (a) --------------------- NameMapper allows access to items in a dictionary using the same dotted notation used to access object attributes in Python. This aspect of NameMapper is known as 'Unified Dotted Notation'. For example, with Cheetah it is possible to write: $customers()['kerr'].address() --OR-- $customers().kerr.address() where the second form is in NameMapper syntax. This only works with dictionary keys that are also valid python identifiers: regex = '[a-zA-Z_][a-zA-Z_0-9]*' AUTOCALLING (b,d) ----------------- NameMapper automatically detects functions and methods in Cheetah $vars and calls them if the parentheses have been left off. For example if 'a' is an object, 'b' is a method $a.b is equivalent to $a.b() If b returns a dictionary, then following variations are possible $a.b.c --OR-- $a.b().c --OR-- $a.b()['c'] where 'c' is a key in the dictionary that a.b() returns. Further notes: * NameMapper autocalls the function or method without any arguments. Thus autocalling can only be used with functions or methods that either have no arguments or have default values for all arguments. * NameMapper only autocalls functions and methods. Classes and callable object instances will not be autocalled. * Autocalling can be disabled using Cheetah's 'useAutocalling' setting. LEAVING OUT 'self' (c,d) ------------------------ NameMapper makes it possible to access the attributes of a servlet in Cheetah without needing to include 'self' in the variable names. See the NAMESPACE CASCADING section below for details. NAMESPACE CASCADING (d) -------------------- ... Implementation details ================================================================================ * NameMapper's search order is dictionary keys then object attributes * NameMapper.NotFound is raised if a value can't be found for a name. Performance and the C version ================================================================================ Cheetah comes with both a C version and a Python version of NameMapper. The C version is significantly faster and the exception tracebacks are much easier to read. It's still slower than standard Python syntax, but you won't notice the difference in realistic usage scenarios. Cheetah uses the optimized C version (_namemapper.c) if it has been compiled or falls back to the Python version if not. s"Tavis Rudd ,s) Chuck Esterbrook i’’’’(tpformatNtNotFoundthasKeyt valueForKeyt valueForNametvalueFromSearchListtvalueFromFrameOrSearchListtvalueFromFramet get_suffixescCsdgS(Ns.pytUi(s.pyR i((((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt™scBseZRS((t__name__t __module__(((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyR scCs7d|}tr'|dt|ƒ7}nt|ƒ‚dS(Nscannot find '%s's in the namespace %s(t._INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONSRR(tkeyt namespacet excString((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt_raiseNotFoundException£s cCsots ‚n_|jd}|jdƒdkrh|d|7}trY|dt|ƒ7}n|f|_n‚dS(Niswhile searchingi’’’’s while searching for '%s's in the namespace %s(t&_ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONStargstfindR R(texctfullNameRtexcStr((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt_wrapNotFoundException©s cCs€t|tƒrtSt|dƒr|t|dƒr5tSt|dƒsbt|dƒsbt|dƒrftSt|dƒr|tSntS(Nt __class__tmrotim_funct func_codet__self__t__init__(t isinstancettypetTruethasattrtFalse(tobj((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt_isInstanceOrClassµs-cCs:t|dƒr||krtSt||ƒr2tStSdS(sDetermine if 'obj' has 'key' thas_keyN(R"R!R#(R$R((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRĒs cCsPt|dƒr#||kr#||St||ƒr?t||ƒSt||ƒdS(NR&(R"tgetattrR(R$R((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRŠs  cCsŹ|jdƒ}x“tt|ƒƒD] }||}t|dƒrZ||krZ||}n4yt||ƒ}Wntk rt||ƒnX|r¼t|dƒr¼t|ƒ r¼|ƒ}q"|}q"W|S(Nt.R&t__call__(tsplittrangetlenR"R'tAttributeErrorRR%(R$tnametexecuteCallablest nameChunkstiRtnextObj((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt _valueForNameŲs   "  cCsDyt|||ƒSWn)tk r?}t|d|d|ƒnXdS(NRR(R3RR(R$R.R/te((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRźscCsW|jdƒd}x0|D](}t||ƒrt||d|ƒSqWt||ƒdS(NR(iR/(R*RR3R(t searchListR.R/RR((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRšs    ccs8|jV|r'x|D] }|VqWn|jVtVdS(N(tf_localst f_globalst __builtins__(t callerFrameR5R((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt _namespacesųs   cs”‡‡‡‡fd†}zq|s8tjƒdd}nˆjdƒd}x-t|ˆƒD]‰tˆ|ƒr[|ƒSq[Wt|ˆƒWd~XdS(NcsGytˆˆdˆƒSWn)tk rB}t|dˆdˆƒnXdS(NR/RR(R3RR(R4(R/R.RR5(s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyt__valueForNamesiiR((tinspecttstackR*R:RR(R5R.R/tframeR;R((R/R.RR5s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRs c CsKz@|s tjƒdd}ntddd|d|d|ƒSWd~XdS(NiiR5R.R/R>(R<R=RtNone(R.R/R>((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRs  cCsT|jdƒd}t||ƒs&tSyt||ƒtSWntk rOtSXdS(s"Determine if 'obj' has the 'name' R(iN(R*RR#RR!R(R$R.R((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pythasName s  (RRRRRRtMixincBs eZdZd„Zd„ZRS(s@@ document mecCs t||ƒS(N(R(tselfR.((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyR8scCs t||ƒS(N(R(RBR((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyR;s(R R t__doc__RR(((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRA6s cCsdtfd„ƒY}d|fd„ƒY}|ƒ}d|_dd„}i|d6|jd 6d d 6i|jd 6d 6|_d}t|jd ƒGHt|dƒGHttƒdƒGHttdƒƒGHttƒdƒGHttƒddtƒGHttƒddtƒGHdS(NtAcBs2eZdZdd„Zdd„Zdd„ZRS(s classVar valsmethod 1 default argcSs|S(N((RBtarg((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pytmethodDssmeth 2 default argcSs i|d6S(Ntitem1((RBRE((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pytmethod2Gssmeth 3 defaultcSs|S(N((RBRE((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pytmethod3Js(R R tclassVarRFRHRI(((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRDBs  tBcBseZdZRS(s classBvar val(R R t classBvar(((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pyRKMst valueForOnetdefaultcSs#idd6dd6dd6}||S(Nsdefault outputRNsoutput option onetonesoutput option twottwo((twhichOnetvalues((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pytfunctionRs  tfuncRFtitemvaltitemt nestedMethodtsubDictsthis is local bsdic.itemtbtdirs a.classVars a.dic.funcR/sa.method2.item1( RARORItdicRRtvarsR8R!(RDRKtaRSRY((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pytexampleAs$     t__main__((!RCt __author__tpprintRR<R#R R!Rt__all__R"timptsetattrt LookupErrorRRRR%RRR3RRR?R:RRR@tCheetah._namemappert C_VERSIONRAR^R (((s?/opt/freeware/lib/python2.7/site-packages/Cheetah/NameMapper.pytƒsL           .   )