U nfd'@sxddlZddlZddlZddddDZedeZedZGdd d Z Gd d d e Z Gd d d e Z dS)N|ccs|]}d|VqdS)z[{0}]N)format).0rrsr) uÀ-ÖuØ-öuø-˿uͰ-ͽuͿ-῿u‌-‍u⁰-↏uⰀ-⿯u、-퟿u豈-﷏uﷰ-�z(:|[A-Z]|_|[a-z]|{0})z2(\-|\.|[0-9]|\xB7|[\u0300-\u036F]|[\u203F-\u2040])c@s4eZdZdZddZGdddZGdddZdS) DataSorterz; Used to sort a map of data depending on it's type cCs|}t|tjst|}|SN) isinstance collections OrderedDictsorted)selfdataZ sorted_datarrr keys_from#s zDataSorter.keys_fromc@seZdZddZdS)zDataSorter.alwayscCst|Sr )rrrrrrr*szDataSorter.always.keys_fromN__name__ __module__ __qualname__rrrrralways)src@seZdZddZdS)zDataSorter.nevercCs|Sr rrrrrr.szDataSorter.never.keys_fromNrrrrrnever-srN)rrr__doc__rrrrrrrr sr c@sHeZdZdZdddgZddd Zd d Zd d ZddZe ddZ dS)Nodea Represents each tag in the tree Each node has _either_ a single value or one or more children If it has a value: The serialized result is <%(tag)s>%(value)s If it has children: The serialized result is <%(wrap)s> %(children)s Which one it is depends on the implementation of self.convert )&z&)z>NTc Cs|||_|||_||_||_|dk r4|nt|_||_||_ |jdkr~t |jt r~|j D]\}}|j |||_qddS)Nflat)sanitize_elementtagwraprdetermine_typetyper data_sorterclosed_tags_foriterables_repeat_wrapr strentitiesreplace) rr"r!rr'r&r%entity replacementrrr__init__Fs   z Node.__init__c s$|j}d\}}|r&d|}d|}|jrD|j|jkrDd|jS|\}}d}|r|jdkr~fdd|D|}n|jrg}|D]F} | }| jd kr||q|gd }|d |||fq|d Sg}|D]} || qd ||d |gSd ||||fS) z,Returns the Node serialized as an xml string)rrzz<{0}>z<{0}/>riterablec3s|]}|VqdSr ) serializercindenterrrrpsz!Node.serialize..rTF) r"rr&rconvertr$r'r/appendjoin) rr3r"endstartvaluechildrencontentresultr1rr2rr/\s4          zNode.serializecCs@|j}t|trdSt|tjjr&dSt|tjjr8dSdSdS)a Return the type of the data on this node as an identifying string * Iterable : Supports "for item in data" * Mapping : Supports "for key in data: value = data[key]" * flat : A string or something that isn't iterable or a mapping rmappingr.N)rr r(r abcMappingIterablerrrrr#s zNode.determine_typec Csd}|j}|j}g}|dkr\|j|}|D],}||}|t|d||j|j|jdq,nV|dkr|D]&}|td|j||j|j|jdqhn t |}|j rd |j ||j }||fS)a Convert data on this node into a (value, children) tuple depending on the type of the data If the type is : * flat : Use self.tag to surround the value. value * mapping : Return a list of tags where the key for each child is the wrap for that node * iterable : Return a list of Nodes where self.wrap is the tag for that node rr=)r'r&r%r.z<{0}>{1}) r$rr%rr5rr'r&r"r(r!r)rvaltyprr:Z sorted_keyskeyitemrrrr4sD   z Node.convertcCsT|rLt|trL|dr$d|}dt|s6dndgdd|DS|SdS)a Convert `wrap` into a valid tag name applying the XML Naming Rules. * Names can contain letters, numbers, and other characters * Names cannot start with a number or punctuation character * Names cannot start with the letters xml (or XML, or Xml, etc) * Names cannot contain spaces * Any name can be used, no words are reserved. :ref: http://www.w3.org/TR/REC-xml/#NT-NameChar xml_rcSs(g|] }t|s t|s dn|qS)rF) NameStartCharmatchNameCharr0rrr sz)Node.sanitize_element..N)r r(lower startswithr6rGrH)r"rrrr s  zNode.sanitize_element)rrNTNN) rrrrr)r-r/r#r4 staticmethodr rrrrr2s  01rc@s,eZdZdZd ddZddZd d d ZdS) ConverterzFLogic for creating a Node tree and serialising that tree into a stringN TcCs||_||_||_dS)aI wrap: The tag that the everything else will be contained within indent: The string that is multiplied at the start of each new line, to represent each level of nesting newlines: A boolean specifying whether we want each tag on a new line. Note that indent only works if newlines is True N)r"indentnewlines)rr"rPrQrrrr-szConverter.__init__cs<|j|j}|sdd}ns"dddfdd}|S)zdReturns a function that given a list of strings, will return that list as a single, indented, stringcSs d|S)Nr)r6)nodeswrappedrrrz*Converter._make_indenter..rcss$|D]}|dD] }|VqqdS)zYield each line in each node N)split)rRnodelinerrreachlinesz*Converter._make_indenter..eachlinecs6|rd}d}nd}d}|||S)a" Indent nodes depending on value of wrapped and indent If not wrapped, then don't indent Otherwise, Seperate each child by a newline and indent each line in the child by one indent unit z {0}z {0}{{0}} rVz{0})rr6)rRrSZ seperatorZ surroundingrZrPrrret s   z%Converter._make_indenter..ret)rPrQ)rrQr\rr[r_make_indenters zConverter._make_indentercCs"|}t|j||||d|S)zICreate a Node tree from the data and return it as a serialized xml string)r"rr'r&r%)r]rr"r/)rrr'r&r%r3rrrbuildszConverter.build)NrOT)TNN)rrrrr-r]r^rrrrrNs $rN) r collections.abcrer6Z start_rangescompilerrGrIr objectrrNrrrrs  ;