o V\I@sdZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl m Z ddl m Z ddl mZddlmZddlmZmZdd lmZmZmZmZdd lmZdd lmZdd lmZmZm Z m!Z!dd l"m#Z#ddl$m%Z%m&Z&ddl'm(Z(ddl)m*Z+ddl,m-Z.ddl/m0Z0m1Z1zddl2m3Z3Wne4yddl5m3Z3YnwerdndZ6d-ddZ7Gddde.Z-Gddde-Z8Gddde-Z9ddZ:Gd d!d!e-Z;Gd"d#d#e-Zd&d'Z?d-d(d)Z@gfd*d+ZAeBd,kre?dSdS).z babel.messages.frontend ~~~~~~~~~~~~~~~~~~~~~~~ Frontends for the message extraction functionality. :copyright: (c) 2013-2019 by the Babel Team. :license: BSD, see LICENSE for more details. )print_functionN) OrderedDict)datetime)getpreferredencoding) __version__)Locale localedata)StringIO string_types text_typePY2)UnknownLocaleError)Catalog)DEFAULT_KEYWORDSDEFAULT_MAPPINGcheck_and_call_extract_fileextract_from_dir)write_mo)read_powrite_po)LOCALTZ)log)Command)DistutilsOptionErrorDistutilsSetupError)RawConfigParserrUrcCsg}t|ttfs |g}|D]'}|durqt|ttfr&|t||dq|ddt||Dqtdd|DsAJ|S)a Make a list out of an argument. Values from `distutils` argument parsing are always single strings; values from `optparse` parsing may be lists of strings that may need to be further split. No matter the input, this function returns a flat list of whitespace-trimmed strings, with `None` values filtered out. >>> listify_value("foo bar") ['foo', 'bar'] >>> listify_value(["foo bar"]) ['foo', 'bar'] >>> listify_value([["foo"], "bar"]) ['foo', 'bar'] >>> listify_value([["foo"], ["bar", None, "foo"]]) ['foo', 'bar', 'foo'] >>> listify_value("foo, bar, quux", ",") ['foo', 'bar', 'quux'] :param arg: A string or a list of strings :param split: The argument to pass to `str.split()`. :return: Nsplitcss|]}|VqdSNstrip).0sr%9/usr/lib/python3/dist-packages/babel/messages/frontend.py Ssz listify_value..css|]}t|tVqdSr ) isinstancer )r#valr%r%r&r'Ts)r(listtupleextend listify_valuer rall)argroutr)r%r%r&r-.s r-c@s.eZdZdZdZdZiZiZeZ dddZ dS)rNr%cCs0||_|d|_d|_d|_d|_d|_dS)NFr) distributioninitialize_options_dry_runverboseforcehelp finalized)selfdistr%r%r&__init__vs zCommand.__init__r ) __name__ __module__ __qualname__as_argsmultiple_value_optionsboolean_optionsoption_aliasesoption_choices distutils_logrr:r%r%r%r&rXsrc@sDeZdZdZdZgdZddgZddZdd Zd d Z d d Z dS)compile_catalogaCatalog compilation command for use in ``setup.py`` scripts. If correctly installed, this command is available to Setuptools-using setup scripts automatically. For projects using plain old ``distutils``, the command needs to be registered explicitly in ``setup.py``:: from babel.messages.frontend import compile_catalog setup( ... cmdclass = {'compile_catalog': compile_catalog} ) .. versionadded:: 0.9 z+compile message catalogs to binary MO files))domain=Dz>domains of PO files (space separated list, default 'messages'))z directory=d.path to base directory containing the catalogsz input-file=izname of the input file) output-file=ozQname of the output file (default '//LC_MESSAGES/.mo')locale=lz locale of the catalog to compile) use-fuzzyfzalso include fuzzy translations) statisticsNz#print statistics about translationsrPrRcCs.d|_d|_d|_d|_d|_d|_d|_dSNmessagesF)domain directory input_file output_filelocale use_fuzzyrRr8r%r%r&r2 z"compile_catalog.initialize_optionscCs<t|j|_|js|jstd|js|jstddSdS)Nzdo not include location comments with filename and line number)z add-location=Nzlocation lines format. If it is not given or "full", it generates the lines with both file name and line number. If it is "file", the line number part is omitted. If it is "never", it completely suppresses the lines (same as --no-location).) omit-headerNz'do not include msgid "" entry in header)rKrLzname of the output filezwidth=wz"set output line width (default 76)no-wrapNzVdo not break long message lines, longer than the output line width, into several lines) sort-outputNz&generate sorted output (default False)) sort-by-fileNz,sort output by file location (default False))zmsgid-bugs-address=Nzset report address for msgid)zcopyright-holder=Nzset copyright holder in output)zproject=Nzset project name in output)zversion=Nzset project version in output)z add-comments=czuplace comment block with TAG (or those preceding keyword lines) in output file. Separate multiple TAGs with commas(,))strip-commentsr$z)strip the comment TAGs from the comments.)z input-paths=Nzofiles or directories that should be scanned for messages. Separate multiple files or directories with commas(,))z input-dirs=Nz@alias for input-paths (does allow files as well as directories).)rrrrrrrz input-paths)z add-commentskeywords)z --keyword)z --mapping)z--output)z--strip-comment-tags)rz mapping-filez output-filerz add-location)fullfilenevercCsd|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_d|_d|_d|_d|_dS)Nzutf-8FT)charsetrno_default_keywords mapping_file no_location add_location omit_headerrX input_dirs input_pathswidthno_wrap sort_output sort_by_filemsgid_bugs_addresscopyright_holderprojectversion add_commentsstrip_commentsinclude_linenor[r%r%r&r2[s* z#extract_messages.initialize_optionscCs|jr|js |j|_ntd|jri}nt}|tt|j ||_ |j s-td|j s4td|j r>|j r>td|j sH|j sHd|_ n |j durSt |j |_ |jr]|jr]td|jrot|jtrntd|j|_n|jdurtdd |jjp~d D|_ng|_|jstd |jD]}tj|std |qt|jpd d |_|jr|js|j|_|js|j |_|j!dkrd|_"dS|j!dkrd|_#dSdS)Nz1input-dirs and input-paths are mutually exclusivez=you must specify new keywords if you disable the default oneszno output file specified0'--no-wrap' and '--width' are mutually exclusiveLz;'--sort-output' and '--sort-by-file' are mutually exclusivez,\s*cSsg|] }|dddqS).r^rr)r#rr%r%r& sz5extract_messages.finalize_options..r%z'no input files or directories specifiedzInput path: %s does not exist,rTrF)$rrrrrcopyupdateparse_keywordsr-rrXrrintrrr(r rerr1dictfromkeyspackageskeysrnrorrrrget_namer get_versionrrr)r8rror%r%r&r]rsf                   z!extract_messages.finalize_optionsc sL}tjd}tjjjjjd}|D]^\}}fdd}t j r@t }t |||jjj|}nt||jj|jd}|D](\} } } } } t j r`| }n t j t j | }|j| d|| fg| | dqPqjdjt||jjjjjjdWddS1swYdS) Nrl)rrrrrcsl|dkrdStjr}n tjtj|}d}|r,dddd|D}jd||dS)Nignorez (%s)z, cSsg|] \}}d||fqS)z%s="%s"r%)r#rvr%r%r&rsz:extract_messages.run..callback..zextracting messages from %s%s)rnroisfilenormpathrpr`rrv)filenamemethodoptionsfilepathoptstrror8r%r&callbacks   z&extract_messages.run..callback)r comment_tagsrstrip_comment_tags) auto_commentscontextzwriting PO template file to %s)rrrrrr) _get_mappingsrtrXrrrrrrrnrorgetcwdrrrrrrrpaddrrvrrrrrrr)r8mappingsrrd method_map options_mapr current_dir extractedrryrcommentsrrr%rr&rfsR    "zextract_messages.runc Csg}|jr1t|jt}t|\}}Wdn1swY|jD] }||||fq$|St|jddrw|jj}| D]4\}}t |t rRtt |\}}ngi}}|D]\}} } ||| f| phi||<qY||||fq@|S|jD] }||t ifqz|S)Nmessage_extractors)rrtpo_file_read_mode parse_mappingrrmgetattrr1rr`r(r r r) r8rfileobjrrrormappingpatternrrr%r%r&rs,    zextract_messages._get_mappingsN)r;r<r=rrrr@r>r?rArBr2r]rfrr%r%r%r&r s$1C =rcCs"|dksJt|tstddS)agValidate the ``message_extractors`` keyword argument to ``setup()``. :param dist: the distutils/setuptools ``Distribution`` object :param name: the name of the keyword argument (should always be "message_extractors") :param value: the value of the keyword argument :raise `DistutilsSetupError`: if the value is not valid rzDthe value of the "message_extractors" parameter must be a dictionaryN)r(rr)r9namevaluer%r%r&check_message_extractorss rc@s:eZdZdZdZgdZdgZddZddZd d Z d S) init_catalogaNew catalog initialization command for use in ``setup.py`` scripts. If correctly installed, this command is available to Setuptools-using setup scripts automatically. For projects using plain old ``distutils``, the command needs to be registered explicitly in ``setup.py``:: from babel.messages.frontend import init_catalog setup( ... cmdclass = {'init_catalog': init_catalog} ) z(create a new catalog based on a POT file)rErFz&domain of PO file (default 'messages')rI) output-dir=rGzpath to output directoryrKrLzQname of the output file (default '//LC_MESSAGES/.po'))rNrOz$locale for the new localized catalogrrrcCs.d|_d|_d|_d|_d|_d|_d|_dSrS) output_dirrXrWrYrUrrr[r%r%r&r2Ar\zinit_catalog.initialize_optionsc Cs|jstd|jstdz t|j|_Wnty'}zt|d}~ww|js2|js2td|jsDt j |j|jd|j d|_t j t j |jsYt t j |j|jrc|jrctd|jsn|jsnd|_dS|jdur{t|j|_dSdS)Nyou must specify the input filez-you must provide a locale for the new catalogz%you must specify the output directoryrgrhrr)rWrrYrparse_localer rXrrnrorprUrrdirnamemakedirsrrr)r8er%r%r&r]Js2      zinit_catalog.finalize_optionscCs|jd|j|jt|jd}t||jd}Wdn1s"wY|j|_t t |_ d|_ t|jd}t |||jdWddS1sNwYdS)Nzcreating catalog %s based on %srj)rYFrl)r)rrvrXrWrtrrYrrnowr revision_daterwrr)r8rrdrr%r%r&rffs  "zinit_catalog.runN r;r<r=rrrr@r2r]rfr%r%r%r&rs rc@s<eZdZdZdZgdZgdZddZddZd d Z d S) update_catalogaCatalog merging command for use in ``setup.py`` scripts. If correctly installed, this command is available to Setuptools-using setup scripts automatically. For projects using plain old ``distutils``, the command needs to be registered explicitly in ``setup.py``:: from babel.messages.frontend import update_catalog setup( ... cmdclass = {'update_catalog': update_catalog} ) .. versionadded:: 0.9 z'update message catalogs from a POT file) rrI)rrGrHr)rNz%do not include msgid entry in headerrMrr)zignore-obsolete=Nz1whether to omit obsolete messages from the output)no-fuzzy-matchingNzdo not use fuzzy matching)update-header-commentNzupdate target header comment)previousNz+keep previous msgids of translated messages)rrzignore-obsoleterrrcCsLd|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ dSrS) rUrWrrXrrYrrignore_obsoleteno_fuzzy_matchingupdate_header_commentrr[r%r%r&r2s z!update_catalog.initialize_optionscCs|jstd|js|jstd|jr|jstd|jr%|jr%td|js/|js/d|_n |jdur:t|j|_|jrE|j rGd|_ dSdSdS)Nrz-you must specify the output file or directoryzyou must specify the localerrF) rWrrXrrYrrrrrr[r%r%r&r]s        zupdate_catalog.finalize_optionsc Cs0g}|jsA|jr||jtj|j|jd|jdfn-t|jD]}tj|j|d|jd}tj |r?|||fq#n ||j|jf|sPt d|j}|sbtj tj |j d}t|j d }t|}Wdn1swwY|D]\}}|jd||j t|d}t|||d}Wdn1swY|j||j|jdtjtj|ttj |} z%t| d } t| ||j|j|j|jd Wdn1swYWn t| zt| |Wq~tyt|t !| |t| Yq~wdS) Nrgrhrirrjzupdating catalog %s based on %s)rYrU)rrl)rrinclude_previousr)"rXrYrmrnrorprrUrqrrrsplitextbasenamerWrtrrrvrrrrtempfile gettempprefixrrrrrremoverenameOSErrorshutilr) r8rzrYr|rUrtemplaterrdtmpnametmpfiler%r%r&rfsz          zupdate_catalog.runNrr%r%r%r&rxs rc@s^eZdZdZdZdeZdddddZee e e dZ d Z dd d Zd d ZddZddZd S)CommandLineInterfacezCommand-line interface. This class provides a simple command-line interface to the message extraction and PO file generation functionality. z%%prog %s [options] %sz %%prog %sz$compile message catalogs to MO filesz:extract messages from source files and generate a POT filez+create new message catalogs from a POT filez0update existing message catalogs from a POT file)compileextractinitrNc Cs~|durtj}tj|jd|jd|_|j|j|j_ |jj ddddd|jj d d d d t j d d|jj ddd d t j dd|jjdt jd|j|dd\}}||j|jrt}tdd|D}|d|d}|D]}t|}|||jf} t| tjjptpddqxdS|s|j d|d} | |j!vr|j d| |"| |dd} | #S)z{Main entry point of the command-line interface. :param argv: list of arguments passed on the command-line N)commandz[args])usagerz--list-locales list_locales store_truez print all known locales and exit)destactionr6z-vz --verbose store_constloglevelzprint as much as possible)r r constr6z-qz--quietzprint as little as possibleF)r rr^cSg|]}t|qSr%ra)r# identifierr%r%r&rAz,CommandLineInterface.run..z %%-%ds %%sasciireplacerzQno valid command or option passed. Try the -h/--help option for more information.zunknown command "%s")$sysargvoptparse OptionParserrrparserdisable_interspersed_args_help print_help add_optionloggingDEBUGERROR set_defaultsINFO parse_args_configure_loggingrr rlocale_identifiersmaxsortrr english_nameprintencodestdoutencodingrrbcommands_configure_commandrf) r8rrargs identifierslongestformatrrYoutputcmdnamecmdinstr%r%r&rf$sV           zCommandLineInterface.runcCsdtd|_|j||jjr|jjd}n t}|j|||td}||dS)Nbabelrz %(message)s) r getLoggerrsetLevelhandlers StreamHandler addHandler Formatter setFormatter)r8rhandler formatterr%r%r&r%Ws     z'CommandLineInterface._configure_loggingcCslt|jtdtdd|jD}dtd|d}t|j}|D] \}}t|||fq'dS)Nz commands:cSrr%r)r#rr%r%r&rirz.CommandLineInterface._help..z %%-%ds %%sr^)r*r format_helpr'r.sortedr`)r8r2r3r.rrr%r%r&rfs zCommandLineInterface._helpc Cs|j|}|}|jr|j|_t|tsJ|tj|j|df|j|d}t |dd}|j D]i\}}} | d} t || dd} d| g} |rS| d || |j| d|j| d } | |krr|jd | 7_q2| |jvr|j| d | d q2| |jvr|j| d| | dq2|j| | | | dq2||\}}|rt|| dd|t|D] \}}t|||qz|W|Sty}z|t|WYd }~|Sd }~ww)zB :type cmdname: str :type argv: list[str] r)rrr>r%=-_z--%sz-%sNz<%s>r )r r6rm)r r6choices)r6defaultrG)command_classesrr(rr2rrrr.rrr"rrmr,rAgetrBr@rr?r$setattrvarsr`ensure_finalizedrrbstr)r8r5rcmdclassr6rr>longshortr6rrHstrsrGrr0keyrerrr%r%r&r/osN        z'CommandLineInterface._configure_commandr )r;r<r=rrVERSIONrr.rDrrrrIrrfr%rr/r%r%r%r&r s& 3 rcCsttjSr )rrfrrr%r%r%r&mainsrVc Csi}g}i}t}t|j|_tr|||n||||D]+}|dkr0t||}q"dd| ddD\}}| ||ft||||<q"|rit |D]\} \}}||vrb||}||f|| <qT||fS)aParse an extraction method mapping from a file-like object. >>> buf = StringIO(''' ... [extractors] ... custom = mypackage.module:myfunc ... ... # Python source files ... [python: **.py] ... ... # Genshi templates ... [genshi: **/templates/**.html] ... include_attrs = ... [genshi: **/templates/**.txt] ... template_class = genshi.template:TextTemplate ... encoding = latin-1 ... ... # Some custom extractor ... [custom: **/custom/*.*] ... ''') >>> method_map, options_map = parse_mapping(buf) >>> len(method_map) 4 >>> method_map[0] ('**.py', 'python') >>> options_map['**.py'] {} >>> method_map[1] ('**/templates/**.html', 'genshi') >>> options_map['**/templates/**.html']['include_attrs'] '' >>> method_map[2] ('**/templates/**.txt', 'genshi') >>> options_map['**/templates/**.txt']['template_class'] 'genshi.template:TextTemplate' >>> options_map['**/templates/**.txt']['encoding'] 'latin-1' >>> method_map[3] ('**/custom/*.*', 'mypackage.module:myfunc') >>> options_map['**/custom/*.*'] {} :param fileobj: a readable file-like object containing the configuration text to parse :see: `extract_from_directory` extractorscSsg|]}|qSr%r!)r#partr%r%r&rrz!parse_mapping..:r^) rr _sectionsr readfp read_filesectionsrr`rrmrs) rrrWrrrsectionrrr~r%r%r&rs(1   rcCsi}|D]F}d|vr|d\}}n|d}}||vrJ|rFg}|dD]}|ddkr:|t|dddfq$|t|q$t|}|||<q|S)aQParse keywords specifications from the given list of strings. >>> kw = sorted(parse_keywords(['_', 'dgettext:2', 'dngettext:2,3', 'pgettext:1c,2']).items()) >>> for keyword, indices in kw: ... print((keyword, indices)) ('_', None) ('dgettext', (2,)) ('dngettext', (2, 3)) ('pgettext', ((1, 'c'), 2)) rYNrr)rrmrr+)stringsrrufuncnameindicesindsxr%r%r&rs    r__main__r )Cr __future__rrrrnrrrr collectionsrrrYrr7rrUrr babel._compatr r r r babel.corer babel.messages.catalogrbabel.messages.extractrrrrbabel.messages.mofilerbabel.messages.pofilerr babel.utilr distutilsrrC distutils.cmdr_Commanddistutils.errorsrr ConfigParserr ImportError configparserrr-rDrrrrobjectrrVrrr;r%r%r%r&sb              *) [  N