a `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/m0Z0m1Z1zddl2m3Z3Wn e4yPddl5m3Z3Yn0er\dndZ6d-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?dS)/z babel.messages.frontend ~~~~~~~~~~~~~~~~~~~~~~~ Frontends for the message extraction functionality. :copyright: (c) 2013-2021 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)RawConfigParserZrUrcCspg}t|ttfs|g}|D]N}|dur*qt|ttfrL|t||dq|ddt||Dq|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$;/usr/lib/python3.9/site-packages/babel/messages/frontend.py Sz listify_value..) isinstancelisttupleextend listify_valuer r)argroutvalr$r$r%r,.s r,c@s.eZdZdZdZdZiZiZeZ dddZ dS)rNr$cCs0||_|d|_d|_d|_d|_d|_dS)NFr) distributioninitialize_optionsZ_dry_runverboseforcehelpZ finalized)selfdistr$r$r%__init__vszCommand.__init__)N) __name__ __module__ __qualname__as_argsmultiple_value_optionsboolean_optionsoption_aliasesoption_choices distutils_logrr7r$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 translationsrMrOcCs.d|_d|_d|_d|_d|_d|_d|_dSNmessagesF)domain directory input_file output_filelocale use_fuzzyrOr5r$r$r%r1sz"compile_catalog.initialize_optionscCs8t|j|_|js |js td|js4|js4tddS)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)rHrIzname 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)ZfullfilenevercCsd|_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_headerrU input_dirs input_pathswidthno_wrap sort_output sort_by_filemsgid_bugs_addresscopyright_holderprojectversion add_commentsstrip_commentsinclude_linenorXr$r$r%r1[s*z#extract_messages.initialize_optionscCs|jr|js|j|_ntd|jr*i}nt}|tt|j ||_ |j sZtd|j shtd|j r||j r|td|j s|j sd|_ n|j durt |j |_ |jr|jrtd|jrt|jtrtd|j|_n6|jdurtdd |jjpd D|_ng|_|js$td |jD] }tj|s*td |q*t|jpXd d |_|jr|js||j|_|js|j |_|j!dkrd|_"n|j!dkrd|_#dS)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).rZrr)r"rr$r$r% sz5extract_messages.finalize_options..r$z'no input files or directories specifiedzInput path: %s does not exist,rTrF)$rrrrrcopyupdateparse_keywordsr,rrUrrintrrr(r rerr0dictfromkeysZpackageskeysrirjrmrrZget_namerZ get_versionrrr)r5rrjr$r$r%rYrs\               z!extract_messages.finalize_optionsc sN}tjd"}tjjjjjd}|D]\}}fdd}t j rt }t |||jjj|}nt||jj|jd}|D]P\} } } } } t j r| }nt j t j | }|j| d|| fg| | dqq8jdjt||jjjjjjdWdn1s@0YdS) Nrg)rrrrrcsl|dkr dStjr}ntjtj|}d}|rXdddd|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)rirjisfilenormpathrkr\rrq)filenamemethodoptionsfilepathZoptstrrjr5r$r%callbacks   z&extract_messages.run..callback)rZ comment_tagsrZstrip_comment_tags)Z auto_commentscontextzwriting PO template file to %s)rrrrrr) _get_mappingsrorUrrrrrrrirjrgetcwdrrrrrrrkaddrrqrrrrrrr)r5mappingsrzr_ method_map options_maprZ current_dirZ extractedrrtryZcommentsrrr$rr%rasN     zextract_messages.runc Cs g}|jr`t|jt}t|\}}Wdn1s80Y|jD]}||||fqHnt|jddr|jj}| D]h\}}t |t rtt |\}}n4gi}}|D]$\}} } ||| f| pi||<q||||fq~n|jD]}||t ifq|S)Nmessage_extractors)rropo_file_read_mode parse_mappingrrhgetattrr0rr\r(r r r) r5rfileobjrrrjrmappingpatternrrr$r$r%rs&*    zextract_messages._get_mappingsN)r8r9r:r{r|r}r=r;r<r>r?r1rYrarr$r$r$r%r~ s"1C=r~cCst|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 zDthe value of the "message_extractors" parameter must be a dictionaryN)r(rr)r6namevaluer$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)rBrCz&domain of PO file (default 'messages')rF) output-dir=rDzpath to output directoryrHrIzQname of the output file (default '//LC_MESSAGES/.po'))rKrLz$locale for the new localized catalogrrrcCs.d|_d|_d|_d|_d|_d|_d|_dSrP) output_dirrUrTrVrRrrrXr$r$r%r1Aszinit_catalog.initialize_optionsc Cs|jstd|jstdzt|j|_Wn,tyZ}zt|WYd}~n d}~00|jsp|jsptd|jst j |j|jd|j d|_t j t j |jst t j |j|jr|jrtd|js|jsd|_n|jdurt|j|_dS)Nyou must specify the input filez-you must provide a locale for the new catalogz%you must specify the output directoryrbrcrr)rTrrVrparse_localer rUrrirjrkrRrmdirnamemakedirsrrr)r5er$r$r%rYJs,     zinit_catalog.finalize_optionscCs|jd|j|jt|jd}t||jd}Wdn1sD0Y|j|_t t |_ d|_ t|jd }t |||jdWdn1s0YdS)Nzcreating catalog %s based on %sre)rVFrg)r)rrqrUrTrorrVrrZnowrZ revision_daterrrr)r5rxr_rzr$r$r%rafs , zinit_catalog.runN r8r9r:r{r|r}r=r1rYrar$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) rrF)rrDrEr)rNz%do not include msgid entry in headerrJrr)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|_ dSrP) rRrTrrUrrVrrignore_obsoleteno_fuzzy_matchingupdate_header_commentrrXr$r$r%r1sz!update_catalog.initialize_optionscCs|jstd|js"|js"td|jr6|js6td|jrJ|jrJtd|js^|js^d|_n|jdurtt|j|_|jr|j rd|_ dS)Nrz-you must specify the output file or directoryzyou must specify the localerrF) rTrrUrrVrrrrrrXr$r$r%rYs       zupdate_catalog.finalize_optionsc Cs>g}|js|jr:||jtj|j|jd|jdfqt|jD]8}tj|j|d|jd}tj |rF|||fqFn||j|jf|st d|j}|stj tj |j d}t|j d}t|}Wdn1s0Y|D]:\}}|jd||j t|d}t|||d}Wdn1sH0Y|j||j|jdtjtj|ttj |} zLt| d ,} t| ||j|j|j|jd Wdn1s0YWnt| Yn0zt| |Wqty6t|t !| |t| Yq0qdS) Nrbrcrdrrezupdating catalog %s based on %s)rVrR)rrg)rrZinclude_previousr)"rUrVrhrirjrkrrRrlrmrsplitextbasenamerTrorrrqrrrrtempfileZ gettempprefixrrrrrremoverenameOSErrorshutilr) r5rurVrvrRrxtemplaterr_ZtmpnameZtmpfiler$r$r%rasj  & .  *   zupdate_catalog.runNrr$r$r$r%rxsrc@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|jr6t}tdd|D}|d|d}|D]>}t|}|||jf} t| tjjp(tp(ddqdS|sH|j d|d} | |j!vrl|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)destactionr4z-vz --verbose store_constloglevelzprint as much as possible)rrconstr4z-qz--quietzprint as little as possibleF)rrrZcSsg|] }t|qSr$r])r" identifierr$r$r%rAr'z,CommandLineInterface.run..z %%-%ds %%sasciireplacerzQno valid command or option passed. Try the -h/--help option for more information.zunknown command "%s")$sysargvoptparse OptionParserrrparserZdisable_interspersed_args_help print_help add_optionloggingDEBUGZERROR set_defaultsINFO parse_args_configure_loggingrrrZlocale_identifiersmaxsortrrZ english_nameprintencodestdoutencodingrr^commands_configure_commandra) r5rrargsZ identifierslongestformatrrVoutputcmdnamecmdinstr$r$r%ra$sV           zCommandLineInterface.runcCsdtd|_|j||jjr.|jjd}nt}|j|||td}||dS)Nbabelrz %(message)s) rZ getLoggerrZsetLevelhandlersZ StreamHandlerZ addHandlerZ FormatterZ setFormatter)r5rZhandler formatterr$r$r%rWs     z'CommandLineInterface._configure_loggingcCslt|jtdtdd|jD}dtd|d}t|j}|D]\}}t|||fqNdS)Nz commands:cSsg|] }t|qSr$r)r"rr$r$r%rir'z.CommandLineInterface._help..z %%-%ds %%srZ)rr format_helprr sortedr\)r5rrr rr|r$r$r%rfs zCommandLineInterface._helpc Cs|j|}|}|jr|j|_|tj|j|df|j|d}t|dd}|jD]\}}} | d} t|| dd} d| g} |r| d || |j | d|j| d } | |kr|jd | 7_qV| |jvr|j| d | d qV| |jvr|j| d| | dqV|j| | | | dqV||\}}|rTt|| dd|t|D]\}}t|||q`z |Wn4ty}z|t|WYd }~n d }~00|S)zB :type cmdname: str :type argv: list[str] r)rr|r;r$=-_z--%sz-%sNz<%s>r)rr4rh)rr4choices)r4defaultr)command_classesrr1rrrr rr}r!rrhr+r>getr?r=rr<rsetattrvarsr\Zensure_finalizedrr^str)r5rrZcmdclassrrr;ZlongZshortr4rrZstrsrrrkeyrerrr$r$r%r osF        $z'CommandLineInterface._configure_command)N)r8r9r:r{rVERSIONrr rAr~rrrrrarrr r$r$r$r%r s$ 3 rcCsttjSr)rrarrr$r$r$r%mainsr'c Csi}g}i}t}t|j|_tr0|||n ||||D]V}|dkr`t||}qDdd| ddD\}}| ||ft||||<qD|rt |D](\} \}}||vr||}||f|| <q||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%rr'z!parse_mapping..:rZ) rrZ _sectionsr ZreadfpZ read_fileZsectionsrr\rrhrn) rrr(rrrsectionrrrwr$r$r%rs(1   rcCsi}|D]}d|vr$|d\}}n |d}}||vr|rg}|dD]:}|ddkrt|t|dddfqH|t|qHt|}|||<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)) r*Nrr)rrhrr*)stringsrrpfuncnameindicesZindsxr$r$r%rs    r__main__)N)N)Cr{Z __future__rrrrirrrr collectionsrrrVrrrr&rrZ babel._compatr r r r Z babel.corer Zbabel.messages.catalogrZbabel.messages.extractrrrrZbabel.messages.mofilerZbabel.messages.pofilerrZ babel.utilrZ distutilsrr@Z distutils.cmdrZ_CommandZdistutils.errorsrrZ ConfigParserr ImportErrorZ configparserrr,rAr~rrrobjectrr'rrr8r$r$r$r%s\            *) [ N