HLc@sdZddkZddkZddkZddkZddkZddkTddkTddkTddk Tddk Tddk TdZ e dZdZdZdZeZd Zd Zd Zd fd YZdfdYZdfdYZdS(splan.py: Objects representing the Plan file for pystyler.py $Revision: 1.54 $ $Date: 2010/09/17 22:40:08 $ Exports: class RawTopic: One parsed line from the Plan file class Plan: Represents the entire Plan file class Topic: Represents one line of the Plan file iN(t*Rs t|tPlant$s.gs.htmltWarningtRawTopiccBseZdZdZRS(sRepresents one line from a topic file. This object is passed from the strictly syntactic part of the topic line processing to the logic that fits it into the tree. Exports: RawTopic ( depth, title, shortName ): [ if (depth is the topic's depth as a nonegative integer, with 0 meaning root, 1 child of root, etc.) and (title is the topic's title as a nonempty string) and (shortName is the topic's short name as a nonempty string) -> return a new RawTopic object representing those values ] .depth: [ as passed to the constructor ] .title: [ as passed to the constructor ] .shortName: [ as passed to the constructor ] cCs||_||_||_dS(N(tdepthttitlet shortName(tselfRRR((s!/u/john/projects/pystyler/plan.pyt__init__Ds  (t__name__t __module__t__doc__R (((s!/u/john/projects/pystyler/plan.pyR2scBseZdZeidZdZddZdZ ddddZ dZ dZ d Z d Zd Zeid eefZd ZdZdZRS(sg Represents the entire Plan file, a catalog of all pages. Exports: Plan ( pathMap, fileName=None, defTemplate=None, unique=0 ): [ if (fileName is a string, defaulting to DEFAULT_PLAN_NAME) and (pathMap is a PathMap object) and (defTemplate is a string or a file-like object containing a template) -> if (fileName names a readable, valid plan file in the context of pathMap) -> return a new Plan object representing that file else -> Log() +:= error message(s) raise IOError ] .pathMap: [ as passed to constructor ] .root: [ the root of the tree of Topic objects ] .defTemplate [ as passed to constructor ] .lookupShortName ( shortName ): [ if shortName is a string -> if shortName (up to but not including any "#" anchor name) matches the short name of a topic in self -> return a Target object representing that topic, and that anchor name if given else -> raise KeyError ] .lookupTemplate ( fileName ): [ if fileName is a string or None -> if (fileName is None) and (the default template file is valid) -> return a Template object representing the default template file else if fileName names a valid template file relative to the starting directory -> return a Template object representing that file else -> Log() +:= error message(s) raise KeyError ] .lookupTitle ( s ): [ if s is a string -> if self contains a topic whose title is s -> return the Topic object for that topic else -> raise KeyError ] .nTopics: [ INV: number of topics in self ] .modEpoch: [ INV: modification epoch timestamp of Plan file ] State/invariants: .tmplPool: [ a TmplPool object containing all Templates mentioned in the plan file ] .shortNameMap: [ a dictionary mapping N |-> T, where N is each short name in self and the corresponding T is the Topic object for that short name ] .titleMap: [ a dictionary mapping K |-> T, where K is each title text in self and the corresponding T is the Topic object for that short name ] .tmplStack: [ a list of one or more Template objects such that the first is the default template and the rest represent the stack of templates pushed by $template commands in the plan file and not yet popped by empty $template commands ] .__unique: [ as passed to constructor ] s ^(.*?)(#.*)$cCs\|ii|}|djo|d}}n|i\}}|i|}t||S(sHFind the topic for a given short name. Preserves anchor names. N(treAnchortmatchtNonetgroupst shortNameMaptTarget(R RtmtpathParttanchorttopic((s!/u/john/projects/pystyler/plan.pytlookupShortNames  cCs4y|i|SWntj o}t|nXdS(sFFind the template that lives in a given file, or the default. N(ttmplPooltIOErrortKeyError(R tfileNametdetail((s!/u/john/projects/pystyler/plan.pytlookupTemplatescCs |i|S(s&Find the topic with title `s' (ttitleMap(R ts((s!/u/john/projects/pystyler/plan.pyt lookupTitlesicCs{||_d|_g|_||_||_t||_|ii|id|djo t }n|i |dS(s&Constructor for a Plan object iN( tpathMaptnTopicst tmplStackt defTemplatet _Plan__uniquetTmplPoolRtappendRtDEFAULT_PLAN_NAMEt _Plan__read(R R"RR%tunique((s!/u/john/projects/pystyler/plan.pyR s       cCspg}d|_h|_h|_ti}t|to+t|}t i |}|i |_ nt|}d|_ x[|i pP|i p5|ito|i|q|i||n|iqWt|idjo'tidt|i|fn|idjotidn|i|tijo tdndS(sRead the plan file and store it in self as a tree of Topics [ if fileName names a readable, valid plan file -> self.root := a tree of topics from the file self.shortNameMap := as invariant self.titleMap := as invariant self.nTopics +:= number of topics from the file else -> Log() +:= error message(s) raise IOError ] lis;There were %d unmatched `$template' lines in the `%s' file.s!The `%s' file contains no topics.s+The plan file contained one or more errors.N(RtrootRRtLogtcountt isinstancetstrtScantpathinfotPathInfotmodEpocht atEndFilet atEndLinet tabMatchArbtCONTROL_LINE_CHARt_Plan__controlLinet_Plan__buildTopictnextLinetlenR$terrortcloseR(R Rt topicStackterrCounttscantinfo((s!/u/john/projects/pystyler/plan.pyt__reads2            cCsw|iti|it}|djo|iddSn|djo|i|n|id|dS(sProcess a control line in the plan file. [ if scan is a Scan object -> if (CONTROL_LINE_CHAR+(the line in scan)) is a valid control line in the context of self -> scan := scan advanced to end of line self := self modified to reflect that control line else -> scan := scan advanced past the valid part, if any Log() +:= error message(s) ] s0Expecting a control line word, e.g., `template'.Nttemplates"`$%s' is not a valid control line.(t deblankLinetstringtlowerttabManytCONTROL_WORD_CSETRR=t_Plan__controlTemplate(R RAtword((s!/u/john/projects/pystyler/plan.pyt __controlLinePs    cCs]|i|io5t|idjo|idqY|id=n|i|dS(scProcess the $template control line [ if "$template"+(line in scan) is a valid $template line -> scan := scan advanced to end of line self := self modified to reflect that line else -> scan := scan advanced past valid parts, if any Log() +:= error message(s) ] is?This end-$template line does not match any open $template line.iN(RER6R<R$R=t_Plan__pushTemplate(R RA((s!/u/john/projects/pystyler/plan.pyt__controlTemplates   cCsWti|id}y|i|}Wntj o dSnX|ii|dS(sProcess a $template-open line [ if line in scan is the name of a readable, valid template file -> scan := scan advanced to end of line self.tmplStack := self.tmplStack + (a new Template object representing that file) else -> scan := scan advanced past valid part, if any Log() +:= error message ] iN(RFtrstripttabRRR$R((R RAttmplNameRD((s!/u/john/projects/pystyler/plan.pyt__pushTemplates   cCsb|i|}|djodSn|i|||i}|pdSn|i|||dS(sProcesses one line of the plan file. [ if (self.root is the tree of existing topics) and (scan is a Scan object) and (topicStack is path-to-topic(previous topic, if any) -> if the line in scan is a valid topic line -> scan := scan advanced to end of line self.root := self.root with that topic added self.shortNameMap +:= a new entry mapping the short name from that line |-> the new Topic made from that line self.titleMap +:= a new entry mapping the title from that line |-> the new Topic made from that line topicStack := path-to-topic(the new Topic made from that line) else -> topicStack := topicStack, possibly trimmed of elements not shallower than new topic line Log() +:= error message(s) ] N(t_Plan__parseTopicRt_Plan__adjustTopicStackRt_Plan__addTopic(R RAR?trawTopictflag((s!/u/john/projects/pystyler/plan.pyt __buildTopics   s7^\s*(?P\%s+)\s*(?P.*)\%s\s*(?P<short>.*)$c���������C���s���|�i��|��i��}�|�d�j�o�|�i�d��d�Sn�t�|�i�d���d�}�t�i�|�i�d���}�t�i�|�i�d���}�t�|�|�|��S(���s\��Check a topic line for syntactic correctness [ if the line in scan is a syntactically valid topic line -> scan := scan advanced to end of line return a RawTopic object containing the fields from that line else -> Log() +:= error message(s) return None ] s���Invalid syntax for a Plan linet���starsi���R���t���shortN( ���t ���tabReMatcht���topicPatR���R=���R<���t���groupRF���RO���R���(���R ���RA���R���R���R���RZ���(����(����s!���/u/john/projects/pystyler/plan.pyt ���__parseTopic!��s����  c���������C���sG���|�t��|��j�o)�|�i�d�|�d�t��|��f��d�Sn�|�|�3d�S(���s��Check & adjust topic stack for a new topic at a given depth [ if (topicStack is a stack of Topic objects) and (newDepth is a positive integer) -> if newDepth > (size of topicStack) -> Log() +:= error message about missing levels return 0 else -> topicStack := first newDepth elements of topicStack return 1 ] sC���This topic is at depth %d while the previous topic was at depth %d.i���i����(���R<���R=���(���R ���RA���R?���t���newDepth(����(����s!���/u/john/projects/pystyler/plan.pyt���__adjustTopicStackF��s ���� c���������C���sj��|��i��i�|�i��}�|�d�j�o�|�i�d�|�i��d�Sn�|��i�i�|�i��o�|�i�d�|�i��d�Sn�|��i�oJ�|��i�i�|�i ��o4�|��i�|�i �}�|�i �t �d�|�i �|�i�f��n�t �|��d�j�o�|�d�}�n�d�}�t �|��|�|�i�|�i �|�i�|��}�|�d�j�o �|�|��_�n�|�|��i�|�i�<|�|��i�|�i �<|�i�|��|��i�d�|��_�d�S(���s��Add a new topic to self and the topicStack [ if (topicStack is a stack of Topic objects of size rawTopic.depth) and (rawTopic is a RawTopic object) -> if rawTopic is invalid -> Log() +:= error message(s) else if rawTopic is valid and topicStack is empty -> self.root := a new Topic made from rawTopic, and no parent self.shortNameMap +:= an entry mapping rawTopic.shortName |-> that new Topic self.titleMap +:= an entry mapping rawTopic.title |-> that new Topic else -> topicStack := topicStack with a new Topic pushed, made from rawTopic, as a new child of the last element of topicStack self.shortNameMap +:= an entry mapping rawTopic.shortName |-> that new Topic ] self.titleMap +:= an entry mapping rawTopic.title |-> that new Topic ] s3���The short name `%s' is not defined in the path map.Ns'���The short name `%s' is already defined.s1���Title `%s' is already defined, for short name %s.i����ii���(���R"���t���expandShortNameR���R���R=���R���t���has_keyR&���R���R���t���msgKindt ���WARNING_KINDR<���t���TopicR���R,���R(���R#���(���R ���R?���RV���RA���t���patht ���otherTopict���parentR���(����(����s!���/u/john/projects/pystyler/plan.pyt ���__addTopicg��s4����           N(���R ���R ���R ���t���ret���compileR���R���R���R���R!���R ���R*���R9���RJ���RM���R:���t ���OUTLINE_CHARt���BAR_CHARR\���RS���RT���RU���(����(����(����s!���/u/john/projects/pystyler/plan.pyR���L���s$���?   ( h 2 * & C  % !Re���c�����������B���s���e��Z�d��Z�d���Z�d���Z�d���Z�d���Z�d���Z�d���Z�d���Z �d���Z �d ���Z �d ���Z �d ���Z �d ���Z�d ���Z�d���Z�d���Z�d���Z�d���Z�d���Z�d���Z�d���Z�RS(���s��Represents one topic in the plan. Exports: Topic ( plan, parent, depth, title, shortName, path ): [ if (plan is a Plan object) and (parent is None for the root topic, else a Topic whose depth is one less than (depth)) and (depth is a nonnegative integer, with 0 meaning root, 1 child of root, etc.) and (title is the topic's title as a nonempty string) and (shortName is the topic's short name as a nonempty string) and (path is a relative path as a string) -> return a new Topic object with those values and an empty list of LinkVar objects ] .plan: [ as passed to constructor ] .parent: [ as passed to constructor ] .depth: [ as passed to constructor ] .title: [ as passed to constructor ] .shortName: [ as passed to constructor ] .path: [ as passed to constructor ] .template: [ default Template object for this topic ] .linkVarList: [ a sequence of LinkVar objects representing variant link texts for self ] .birthOrder(): [ if self is the root topic -> return 0 else -> return self's birth order relative to its parent, >=0 ] .nChildren(): [ returns the number of self's children ] .childList(): [ returns a new list of self's children in birth order ] .nthChild(n): [ if n is an integer -> if self has at least n-1 children -> return self's nth children, counting from 0 else -> raise IndexError ] .relPath(toTarget): [ if toTarget is a Target object -> return the pathname (and optional anchor) which, when used in self's directory, points to the output file of toTarget ] .addLinkVar(linkVar): [ if linkVar is a LinkVar object whose .shortName matches self.shortName -> self := self with linkVar added to its .linkVarList ] .url(): [ returns the URL of topic's HTML file ] .fullPath(): [ returns a list of integers [c0, c1, ..., ci] such that self is root.nthChild(c0).nthChild(c1). ... .nthChild(ci) ] .isOnPath(nodeId): [ if nodeId is None or a NodeId object -> if (nodeId is None) and (self is the root) -> 1 else if (nodeId is a NodeId) and (self.fullPath is a prefix of, or equal to, nodeId's path) -> return 1 else -> return 0 ] .find(nodeId): [ if (self is the root Topic) and (nodeId is None or a NodeId object) -> if nodeId is None -> return self else if nodeId describes the path to a node that exists in self's topic tree -> return that Topic object else -> return None ] .expandTree(force, outRoot): [ if (force is a boolean) and (outRoot is None or a string) -> subtree-output-pages(self, force, outRoot, pathMap, plan) := subtree-contents(self, force, outRoot, pathMap, plan, subtree-files(self, pathMap, plan)) Log() +:= errors, if any, from that expansion plan := plan with text variants added from <RR> elements in subtree-files return number of pages actually written ] State/Invariants: .__tree: [ a Tree object connecting self to its parent, and children if any ] c���������C���s���|�|��_��|�|��_�|�|��_�|�|��_�|�|��_�|�|��_�|�i�d�|��_�g��|��_�|�o�t �|�i �|���|��_ �n�t �d�|���|��_ �d�S(���s*���Constructor for the Topic object. iN( ���t���planRh���R���R���R���Rf���R$���RD���t ���linkVarListt���Treet ���_Topic__treeR���(���R ���Rn���Rh���R���R���R���Rf���(����(����s!���/u/john/projects/pystyler/plan.pyR ���%��s����       c���������C���s"���d�d�|��i��d�|��i�|��i�f�S(���s$���For debug display of topics s���topic(%s %s (%s))R����i���(���R���R���R���(���R ���(����(����s!���/u/john/projects/pystyler/plan.pyt���__str__@��s����c���������C���s ���|��i��i�S(���s4���Returns self's birth order, counting from 0 (���Rq���t ���birthOrder(���R ���(����(����s!���/u/john/projects/pystyler/plan.pyRs���I��s����c���������C���s ���|��i��i���S(���s.���Returns the number of self's children (���Rq���t ���nChildren(���R ���(����(����s!���/u/john/projects/pystyler/plan.pyRt���Q��s����c���������C���s1���g��}�x$�|��i��i�D]�}�|�i�|�i��q�W|�S(���s.���Returns a new list of self's children (���Rq���t ���childListR(���t���value(���R ���t���resultt���child(����(����s!���/u/john/projects/pystyler/plan.pyRu���Y��s ���� �c���������C���s���|��i��i�|��}�|�i�S(���s#���Return self's (n)th child. (���Rq���t���nthChildRv���(���R ���t���nt ���childTree(����(����s!���/u/john/projects/pystyler/plan.pyRy���k��s����c���������C���s���t��i�|��i�d��}�t��i�|�i�i�d��}�xN�t�|��d�j�o:�t�|��d�j�o'�|�d�|�d�j�o�|�d�=|�d�=q0�Wg��}�|�i�d�t�|��d��|�i�t��i�|�d���|�i�t��|�i�o�|�i�|�i��n�t��i�|�d��S(���s��Find the pathname from self's topic to the given target. Method: Self's and toTarget's paths should, in general, have this form: d1 / d2 / ... / dn / f where the di are directories and f is the unqualified filename. 1. First find the largest sequence of directories d1, d2, ... that is a prefix of both self's and toTarget's paths, e.g.: self's path: d1/d2/.../dc/a1/a2/.../aj/fa other's path: d1/d2/.../dc/b1/b2/.../bk/fb 2. Form the two lists that remain when these prefixes are removed, e.g.: self: a1/a2/.../aj/fa other: b1/b2/.../bk/fb 3. The result consists of: a. One "../" for each a1, a2, ..., aj; this gets us up to the lowest directory that is a parent of self and the other. b. The sequence "b1/b2/.../bk/fb". c. The suffix ".html". d. The anchor from toTarget, if any. Examples: self's path toTarget's path result ----------- --------------- ------ here/new here/new new.html here/old here/new new.html here/old here/there/new there/new.html foo/x/y/z/a foo/ear/danke/b ../../../ear/danke/b.html t���/i���i����s���../t����( ���RF���t���splitRf���R���R<���R(���t���joint���HTML_EXTR���(���R ���t���toTargett���fromListt���toListRw���(����(����s!���/u/john/projects/pystyler/plan.pyt���relPath{��s����%   c���������C���s���|��i��i�|��d�S(���s*���Add a LinkVar to self.linkVarList N(���Ro���R(���(���R ���t���linkVar(����(����s!���/u/john/projects/pystyler/plan.pyt ���addLinkVar��s����c���������C���s���|��i��i�i�|��i�d�S(���s-���Return the URL of topic's HTML page. s���.html(���Rn���R"���t���rootURLRf���(���R ���(����(����s!���/u/john/projects/pystyler/plan.pyt���url��s����c���������C���s ���|��i��i���S(���sH���Return route from root->self as a sequence of birthOrder values (���Rq���t���fullPath(���R ���(����(����s!���/u/john/projects/pystyler/plan.pyR�����s����c���������C���sA���|�d�j�o �|��i�d�j�o�d�Sq=�d�Sn�|�i�|��i��Sd�S(���s;���Is self somewhere on the path described by nodeId? i���i����N(���R���Rh���t���isOnPathRq���(���R ���t���nodeId(����(����s!���/u/john/projects/pystyler/plan.pyR�����s���� c���������C���s)���|�d�j�o�|��Sn�|�i�|��i��Sd�S(���sH���Find the topic that corresponds to a given NodeId; self is root N(���R���t���findRq���(���R ���R���(����(����s!���/u/john/projects/pystyler/plan.pyR�����s���� c���������C���sb���d�}�|�|��i��|�|��}�x?�t�|��i����D]+�}�|��i�|��}�|�|�i�|�|��}�q/�W|�S(���s>���Read all body files at or under self and expand them. i����(���t���expandt���rangeRt���Ry���t ���expandTree(���R ���t���forcet���outRoott���nChangedt���childxRx���(����(����s!���/u/john/projects/pystyler/plan.pyR�����s�����c���������C���s���|��i��t�}�|��i�|��}�|��i�|�|�|��o�d�Sn�y�t�|��|��}�Wn�t�j �o �d�Sn�X|��i�|��}�|�p�d�Sn�|�i�i�|�|��|�i ���d�S(���sG��Expand self's body file (unless up to date and not force) [ if (force is a Boolean) and (outRoot is None or a string) -> if (not force) and (self's body page exists) and (self's output page exists in outRoot and is up to date) -> return 0 else (if self's body page exists and is valid and its template exists and is valid) -> self's output page := expansion of self's body page in context of plan and the body page's template, in path starting at outRoot plan := plan with self's effective template added if not already present return 1 else -> Log() +:= error message(s) ] i����Ni���( ���Rf���t���BODY_EXTt���_Topic__outPatht���_Topic__pageUpToDatet���BodyR���t���_Topic__openOutt ���etemplateR���R>���(���R ���R���R���t���bodyNamet���htmlNamet���bodyt���outFile(����(����s!���/u/john/projects/pystyler/plan.pyR�����s����    c���������C���s���y�t��i�|��i�}�Wn�t�j �o �d�Sn�Xy�t��i�|��i�}�Wn�t�j �o �}�d�Sn�X|��i�i�}�|�|�j�o0�|�|�j�o#�|�|��i�i�j�o�|� o�d�Sn�d�Sd�S(���s��Check to see if the output page is okay as it stands. [ if (bodyName is the name of self's body page as a string) and (htmlName is the name of self's output page as a string) and (force is a Boolean) -> if (self's output page exists and is up to date) and (self's body page exists) and (not force) -> return 1 else -> return 0 ] NOTE: There is one thing not considered in our definition of "up to date". If the actual body file contains a <TEMPLATE> tag, we don't check to see if the template named in that tag has a newer modification time than the HTML file. The <TEMPLATE> tag is deprecated because we don't want to have read every body file to see if it has such a tag; that would defeat half the purpose of this rewrite, which was to speed up rebuilds. i����i���N(���R2���R3���R4���t���OSErrorRD���Rn���(���R ���R���R���R���t ���oldModTimet ���bodyModTimeR���t ���templateTime(����(����s!���/u/john/projects/pystyler/plan.pyt���__pageUpToDate]��s����     c���������C���s1���|��i��t�}�|�o�t�i��i�|�|��}�n�|�S(���s��Find the pathname of self's output file [ if outRoot is None or a string -> if outRoot is None -> return self.path + HTML_EXT else -> return outRoot + ("/" if needed) + self.path + HTML_EXT ] (���Rf���R���t���osR���(���R ���R���R���(����(����s!���/u/john/projects/pystyler/plan.pyt ���__outPath��s���� c������ ���C���s���y�t��|�d��SWn�t�j �o�n�X|��i�|��p�d�Sn�y�t��|�d��SWn9�t�j �o-�}�t���i�d�|�t�|��f��d�Sn�Xd�S(���s��Try to open outName anew, possible creating directories [ if outName is a string -> if outName can be created anew, with any directories in outName's path created if necessary -> return a writeable handle for that new, empty file else -> possibly create some of the directories in outName's path Log() +:= error message(s) return None ] t���ws.���Can't create a new, empty output file `%s': %sN(���t���openR���t���_Topic__makeDirsR���R-���R=���R0���(���R ���t���outNameR���(����(����s!���/u/john/projects/pystyler/plan.pyt ���__openOut��s����  c���������C���s<���|��i��|��}�x&�|�D]�}�|��i�|��p�d�Sq�q�Wd�S(���s��Try to make all nonexistent directories along the given path [ if path is a path name as a string -> if all directories in path exist -> return 1 else if all nonexistent directories in path can be created top to bottom -> create those directories return 1 else -> possibly create some of those directories Log() +:= error message(s) return 0 ] i����i���(���t���_Topic__buildDirListt���_Topic__creDir(���R ���Rf���t���dirListt���dir(����(����s!���/u/john/projects/pystyler/plan.pyt ���__makeDirs��s ���� �  c��� ������C���s}���t��i�i�|��\�}�}�t�i�|�d��}�g��}�d�}�d�}�x:�|�D]2�}�|�|�|�}�d�}�|�o�|�i�|��qC�qC�W|�S(���sP��Find the list of all directory names in a given path [ if path is a string containing a path name -> if path has the form "/d0/d1/.../dn/f" -> return a list ["/d0", "/d0/d1", ..., "/d0/d1/.../dn"] else -> return a list ["d0", "d0/d1", ..., "d0/d1/.../dn" ] R|���R}���(���R���Rf���R~���RF���R(���( ���R ���Rf���t���dirPartt���filePartt���LRw���t���curPatht���sept���part(����(����s!���/u/john/projects/pystyler/plan.pyt���__buildDirList��s���� � c���������C���s���y�t��i�|��}�Wn�t�j �o�}�d�}�n�X|�o>�|�i���p �|�i���o�d�Sqv�t���i�d�|��d�Sn�y�t�i �|��d�SWn9�t�j �o-�}�t���i�d�|�t �|��f��d�Sn�Xd�S(���s��If path does not exist, try to create it as a directory [ if path is a string -> if path names an existing directory -> return 1 else if path names a directory that can be created -> create that directory return 1 else -> Log() +:= error message(s) return 0 ] i���sS���Trying to create directory `%s' but there is an existing file or link by that name.i����s���Can't create directory `%s': %sN( ���R2���R3���R���R���t���isDirt���isLinkR-���R=���R���t���mkdirR0���(���R ���Rf���RB���R���(����(����s!���/u/john/projects/pystyler/plan.pyt���__creDirS��s"����     (���R ���R ���R ���R ���Rr���Rs���Rt���Ru���Ry���R���R���R���R���R���R���R���R���R���R���R���R���R���R���(����(����(����s!���/u/john/projects/pystyler/plan.pyRe�����s*���S      D    # L ;  3 1 =(���R ���RF���Rj���t���copyt���timeR���t���logt���csetRA���t���treeRD���R���Rl���t���Csett���PLAN_WHITE_SETRm���R)���R8���t���lettersRI���R���R���Rd���R���R���Re���(����(����(����s!���/u/john/projects/pystyler/plan.pys���<module> ���s2���            ��