Ë ZjÕ7·B;rãó—dZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z dZ dZ dZ ej d ej"«Zej d «Zej(e«Zd „Zd „Zd „Zd„Zd„Zd„Zd„Zd„Zy)a Parsing and reformatting of usage messages. The :mod:`~humanfriendly.usage` module parses and reformats usage messages: - The :func:`format_usage()` function takes a usage message and inserts ANSI escape sequences that highlight items of special significance like command line options, meta variables, etc. The resulting usage message is (intended to be) easier to read on a terminal. - The :func:`render_usage()` function takes a usage message and rewrites it to reStructuredText_ suitable for inclusion in the documentation of a Python package. This provides a DRY solution to keeping a single authoritative definition of the usage message while making it easily available in documentation. As a cherry on the cake it's not just a pre-formatted dump of the usage message but a nicely formatted reStructuredText_ fragment. - The remaining functions in this module support the two functions above. Usage messages in general are free format of course, however the functions in this module assume a certain structure from usage messages in order to successfully parse and reformat them, refer to :func:`parse_usage()` for details. .. _DRY: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself .. _reStructuredText: https://en.wikipedia.org/wiki/ReStructuredText éN)Ú import_module)ÚStringIO)ÚdedentÚsplit_paragraphsÚtrim_empty_lines)Úfind_meta_variablesÚ format_usagerÚ inject_usageÚ parse_usageÚ render_usageÚ USAGE_MARKERzUsage:úSupported options:aê # Make sure whatever we're matching isn't preceded by a non-whitespace # character. (?zformat_usage..zs ø€™i¨°_ÕEóÚ) Úhumanfriendly.terminalrrrÚstripÚ splitlinesÚ startswithr ÚappendÚreplace_special_tokensÚjoin)Ú usage_textÚformatted_linesÚmeta_variablesÚlinerrs @@rr r \sˆù€÷&BØ€OÜ(¨Ó4€NØ× Ñ Ó"×-Ñ-¨dÖ3ˆØ �?‰?œ<Ô (à × "Ñ "¡9¨T¸Ô#IÕ Jð × "Ñ "Ô#9Ø�nÜEó$õ ð 4ð �7‰7�?Ó #Ð#rcóø—t«}tj|«D]N}|jd«}|j d«sŒ&|j d«\}}}|sŒ>|j |«ŒPt|«S)a‘ Find the meta variables in the given usage message. :param usage_text: The usage message to parse (a string). :returns: A list of strings with any meta variables found in the usage message. When a command line option requires an argument, the convention is to format such options as ``--option=ARG``. The text ``ARG`` in this example is the meta variable. rÚ-Ú=)ÚsetÚ USAGE_PATTERNÚfinditerÚgrouprÚ partitionÚaddÚlist)r"r$ÚmatchrÚoptionÚ_Úvalues rrrsn€ô“U€NÜ×'Ñ'¨ Ö3ˆØ— ‘ ˜A“ˆØ × Ñ ˜CÕ Ø$Ÿ™¨sÓ3Ñ ˆF�A�uÚØ×"Ñ" 5Õ)ð 4ô �Ó Ðrcó¤—g}g}t|«}|r2|dtk(}|j|jd««|rn|rŒ2tj d|«|r×|jt |jd«««g}|r~tjd|d«D�cgc]&}|sŒ|j«rŒ|j«‘Œ(}}td„|D««rn#|j|jd««|rŒ~|jt dj|«««|rŒ×tj d|«||fScc}w)aÊ Parse a usage message by inferring its structure (and making some assumptions :-). :param text: The usage message to parse (a string). :returns: A tuple of two lists: 1. A list of strings with the paragraphs of the usage message's "introduction" (the paragraphs before the documentation of the supported command line options). 2. A list of strings with pairs of command line options and their descriptions: Item zero is a line listing a supported command line option, item one is the description of that command line option, item two is a line listing another supported command line option, etc. Usage messages in general are free format of course, however :func:`parse_usage()` assume a certain structure from usage messages in order to successfully parse them: - The usage message starts with a line ``Usage: ...`` that shows a symbolic representation of the way the program is to be invoked. - After some free form text a line ``Supported options:`` (surrounded by empty lines) precedes the documentation of the supported command line options. - The command line options are documented as follows:: -v, --verbose Make more noise. So all of the variants of the command line option are shown together on a separate line, followed by one or more paragraphs describing the option. - There are several other minor assumptions, but to be honest I'm not sure if anyone other than me is ever going to use this functionality, so for now I won't list every intricate detail :-). If you're curious anyway, refer to the usage message of the `humanfriendly` package (defined in the :mod:`humanfriendly.cli` module) and compare it with the usage message you see when you run ``humanfriendly --help`` and the generated usage message embedded in the readme. Feel free to request more detailed documentation if you're interested in using the :mod:`humanfriendly.usage` module outside of the little ecosystem of Python packages that I have been building over the past years. rzParsed introduction: %sz,\sc3óFK—|]}tj|«–—Œy­w©N)ÚOPTION_PATTERNr0)Ú.0Úts rÚ zparse_usage..ßsèø€Ð;±F¨q”>×'Ñ'¨×*±Fùs‚!ú zParsed options: %s) rÚSTART_OF_OPTIONS_MARKERrÚpopÚloggerÚdebugrÚreÚsplitÚisspacerÚallr!)ÚtextÚ introductionÚdocumented_optionsÚ paragraphsÚ end_of_introÚ descriptionr9Útokenss rr r •s5€ðd€LØÐä! $Ó'€Já à" 1™ Ô)@Ñ@ˆ à×јJŸN™N¨1Ó-Ô.á Ø ò ô ‡L�LÐ*¨LÔ9á Ø×!Ñ!¤&¨¯©¸Ó):Ó";Ô<؈ Ùô *,¯©°&¸*ÀQ¹-Ô)HÓbÑ)H AÊAÐVW×V_ÑV_ÕVa�a—g‘g•iÐ)HˆFÐbÜÑ;±FÓ;Ô;Øà×"Ñ" :§>¡>°!Ó#4Ô5òð ×!Ñ!¤&¨¯©°[Ó)AÓ"BÔCò ô  ‡L�LÐ%Ð'9Ô:Ø Ð+Ð +Ð+ùòcsÂ$E Â,E Â=E c óć —t|«Š t|«\}}|D�cgc]}t|‰ «‘Œ}}|rù|jdj gd¢««t «}t j|«}|rq|jd«}|jd«}|jt|‰ «dj ˆ fd„t|«D««j«g«|rŒq|j«j«} |jdj d„| D«««tjd|«dj d„|D««Scc}w) zÔ Reformat a command line program's usage message to reStructuredText_. :param text: The plain text usage message (a string). :returns: The usage message rendered to reStructuredText_ (a string). Ú )z.. csv-table::z :header: Option, Descriptionz :widths: 30, 70rrr;c3ó6•K—|]}t|‰«–—Œy­wr6)Úrender_paragraph)r8Úpr$s €rr:zrender_usage..søèø€ÐhÑJgÀQÔ-¨a°×@ÑJgùsƒc3ó&K—|] }d|z–—Œ y­w)z %sNr)r8r%s rr:zrender_usage..sèø€ÐE¹9°4 ¨$¥¹9ùs‚zRendered output: %sc3ó2K—|]}t|«–—Œy­wr6)r)r8Úos rr:zrender_usage..sèø€Ð;±F¨qÔ'¨×*±Fùs‚)rr rNrr!rÚcsvÚwriterr=ÚwriterowrÚrstripÚgetvaluerr>r?) rDrEÚoptionsrOÚoutputÚ csv_bufferÚ csv_writerÚvariantsrIÚ csv_linesr$s @rr r ês/ø€ô)¨Ó.€NÜ'¨Ó-Ñ€L�'Ù;GÓ H¹<°aÔ˜q .Õ1¸<€FÐ HÙØ� ‰ �d—i‘iò! ó ô ô “Zˆ Ü—Z‘Z  Ó+ˆ ÙØ—{‘{ 1“~ˆHØ!Ÿ+™+ a›.ˆKØ × Ñ Ü  ¨>Ó:Ø—‘ÓhÔJZÐ[fÔJgÓhÓh×pÑpÓrð!ô òð×'Ñ'Ó)×4Ñ4Ó6ˆ Ø� ‰ �d—i‘iÑE¹9ÓEÓEÔFÜ ‡L�LÐ&¨Ô/Ø �;‰;Ñ;±FÓ;Ó ;Ð;ùò)IsŸEcóv—ddl}t|«j}|jdt |«zdz«y)a‹ Use cog_ to inject a usage message into a reStructuredText_ file. :param module_name: The name of the module whose ``__doc__`` attribute is the source of the usage message (a string). This simple wrapper around :func:`render_usage()` makes it very easy to inject a reformatted usage message into your documentation using cog_. To use it you add a fragment like the following to your ``*.rst`` file:: .. [[[cog .. from humanfriendly.usage import inject_usage .. inject_usage('humanfriendly.cli') .. ]]] .. [[[end]]] The lines in the fragment above are single line reStructuredText_ comments that are not copied to the output. Their purpose is to instruct cog_ where to inject the reformatted usage message. Once you've added these lines to your ``*.rst`` file, updating the rendered usage message becomes really simple thanks to cog_: .. code-block:: sh $ cog.py -r README.rst This will inject or replace the rendered usage message in your ``README.rst`` file with an up to date copy. .. _cog: http://nedbatchelder.com/code/cog/ rNrLr;)ÚcogrÚ__doc__Úoutr )Ú module_namer_r"s rr r s3€ó@ܘ{Ó+×3Ñ3€J؇G�GˆD”<  Ó+Ñ +¨fÑ 4Õ5rcó>—|jt«r.|j«}d|d›ddj|dd«›d�S|dk(rd|zSt j d |«rj|j «}|dj«s|D�cgc]}d |z‘Œ }}|jdd «|jdd «d j|«S|dj«s7t jdd|«}|jdd«}t||d„«}|Scc}w)Nz**rz** `Ú éÚ`rz**%s**z ^\s*\$\s+\Sz %sz.. code-block:: shrrLz`(.+?)'z"\1"Ú*z\*có —d|zS)Nz``%s``r)rs rrz"render_paragraph..Ns €˜( UÒ*r) rr rAr!r@r0rrBÚinsertÚsubÚreplacer )Ú paragraphr$rJÚlinesr%s rrNrN/s€ð×ÑœLÔ)Ø—‘Ó"‰Ø & q£ ¨3¯8©8°F¸1¸2°JÕ+?Ð@Ð@àÐ(Ò(ؘ)Ñ#Ð#ä ‡x�x�  Ô*à×$Ñ$Ó&ˆà˜‰|×#Ñ#Ô%á/4Ó5©u t�V˜d“]¨uˆEÐ5Ø � ‰ �QÐ,Ô-Ø � ‰ �Q˜ÔØ�y‰y˜ÓÐð �Q‰<× Ñ Ô !ä—F‘F˜9 g¨yÓ9ˆ à×%Ñ% c¨5Ó1ˆ ä*Ø �~Ù *ó ˆ ð Ðùò#6s Dcób—tjtjt||¬«|«S)N)r$Ú replace_fn)r*rjÚ functoolsÚpartialÚreplace_tokens_callback)rDr$ros rr r Ss0€Ü × Ñ œY×.Ñ.ÜØ%Øôð ó  ð rcól—|jd«}tjd|«r||vs||«}|S)Nrz^[A-Z][A-Z0-9_]+$)r,r@r0)r0r$rors rrrrr[s4€Ø �K‰K˜‹N€EÜ �H‰HÐ(¨%Ô 0°UÀ.Ñ5PÙ˜5Ó!ˆØ €Lr)r`rSrpÚloggingr@Ú importlibrÚhumanfriendly.compatrÚhumanfriendly.textrrrÚ__all__r r<ÚcompileÚVERBOSEr*r7Ú getLoggerÚ__name__r>r rr r r rNr rrrrrÚr}s·ðñó: ÛÛÛ õ$õ*ßIÑIð €ð€ Ø?à.ÐØMð�— ‘ ðð"‡Z�Zó#€ ð(�—‘Ð:Ó;€ð ˆ× Ñ ˜8Ó $€ò $òF ò,R,òj<ò@"6òJ!òH ór