3

X'ícC¤ã@s4dZddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
ddlmZddl
m
Z
ddlmZddlmZddlmZmZdd	lmZdd
lmZmZddlmZmZmZmZddlm Z dd
l!m"Z"m#Z#ddl$m%Z%ej&dƒZ'yPddl(m)Z*e'Z+yddl,m-Z-m.Z.m/Z/Wn"e0k
rBe1Z-Z.Z/YnXWnBe0k
rˆddl2m'Z+ddl3m)Z*ddl4m5Z-m6Z.m7Z/YnXd-dd„Z8Gdd„de*ƒZ)Gdd„de)ƒZ9dd„Z:Gdd„de)ƒZ;dd„Z<Gd d!„d!e)ƒZ=Gd"d#„d#e)ƒZ>Gd$d%„d%ƒZ?d&d'„Z@d.d(d)„ZAgfd*d+„ZBeCd,kr0e@ƒdS)/zÕ
    babel.messages.frontend
    ~~~~~~~~~~~~~~~~~~~~~~~

    Frontends for the message extraction functionality.

    :copyright: (c) 2013-2022 by the Babel Team.
    :license: BSD, see LICENSE for more details.
éN)ÚOrderedDict)ÚRawConfigParser)Údatetime)ÚStringIO)Ú__version__)ÚLocaleÚ
localedata)ÚUnknownLocaleError)ÚCatalogÚDEFAULT_HEADER)ÚDEFAULT_KEYWORDSÚDEFAULT_MAPPINGÚcheck_and_call_extract_fileÚextract_from_dir)Úwrite_mo)Úread_poÚwrite_po)ÚLOCALTZÚbabel)ÚCommand)ÚOptionErrorÚ
SetupErrorÚ	BaseError)Úlog)ÚDistutilsOptionErrorÚDistutilsSetupErrorÚDistutilsErrorcCsŠg}t|ttfƒs|g}xV|D]N}|dkr,qt|ttfƒrN|jt||dƒq|jdd„t|ƒj|ƒDƒƒqWtdd„|Dƒƒs†t‚|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:
    N)Úsplitcss|]}|jƒVqdS)N)Ústrip)Ú.0Ús©r!ú8/tmp/pip-build-gk9425m9/babel/babel/messages/frontend.pyú	<genexpr>Ysz listify_value.<locals>.<genexpr>css|]}t|tƒVqdS)N)Ú
isinstanceÚstr)rÚvalr!r!r"r#Zs)	r$ÚlistÚtupleÚextendÚ
listify_valuer%rÚallÚAssertionError)ÚargrÚoutr&r!r!r"r*4s
"r*c@s.eZdZdZfZfZiZiZeZ	ddd„Z
dS)rNcCs0||_|jƒd|_d|_d|_d|_d|_dS)NFr)ÚdistributionÚinitialize_optionsÚ_dry_runÚverboseÚforceÚhelpÚ	finalized)ÚselfÚdistr!r!r"Ú__init__|szCommand.__init__)N)Ú__name__Ú
__module__Ú__qualname__Úas_argsÚmultiple_value_optionsÚboolean_optionsÚoption_aliasesÚoption_choicesÚ
distutils_logrr8r!r!r!r"r^src	@sNeZdZdZdZd d!d"d#d$d%d&gZddgZdd„Zdd„Zdd„Z	dd„Z
dS)'Úcompile_catalogaÛCatalog 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=ÚDú>domains of PO files (space separated list, default 'messages')ú
directory=Údú.path to base directory containing the catalogsúinput-file=Úiúname of the input fileúoutput-file=ÚoúQname of the output file (default '<output_dir>/<locale>/LC_MESSAGES/<domain>.mo')úlocale=Úlú locale of the catalog to compileú	use-fuzzyÚfúalso include fuzzy translationsÚ
statisticsNú#print statistics about translationscCs.d|_d|_d|_d|_d|_d|_d|_dS)NÚmessagesF)ÚdomainÚ	directoryÚ
input_fileÚoutput_fileÚlocaleÚ	use_fuzzyrU)r6r!r!r"r0¬sz"compile_catalog.initialize_optionscCs@t|jƒ|_|jr$|jr$tdƒ‚|jr<|jr<tdƒ‚dS)Nz<you must specify either the input file or the base directoryz=you must specify either the output file or the base directory)r*rXrZrYrr[)r6r!r!r"Úfinalize_optionsµs
z compile_catalog.finalize_optionscCs\d}x6|jD],}x&|j|ƒjƒD]\}}|t|ƒ7}q WqW|rP|jjd|ƒ|rXdSdS)Nrz%d errors encountered.é)rXÚ_run_domainÚitemsÚlenrÚerror)r6Zn_errorsrXÚcatalogÚerrorsr!r!r"Úrun¼szcompile_catalog.runcCs|g}g}|jsÄ|jr\|j|jtjj|j|jd|dƒfƒ|jtjj|j|jd|dƒƒnfx¬tj|jƒD]T}tjj|j|d|dƒ}tjj|ƒrj|j||fƒ|jtjj|j|d|dƒƒqjWnF|j|j|jfƒ|j	rê|j|j	ƒn |jtjj|j|jd|dƒƒ|st
dƒ‚i}xXt|ƒD]J\}\}}||}t|dƒ}	t
|	|ƒ}
WdQRX|jrÌd}x*t|
ƒdd…D]}|jr||d7}q|Wd}
t|
ƒr´|dt|
ƒ}
|jjd	|t|
ƒ|
|ƒ|
jrð|jrð|jjd
|ƒq(t|
jƒƒ||
<}x6|D].\}}x"|D]}|jjd||j|ƒqWq
W|jjd||ƒt|d
ƒ}t||
|jdWdQRXq(W|S)NÚLC_MESSAGESz.poz.mozno message catalogs foundÚrbrr_édz)%d of %d messages (%d%%) translated in %sz'catalog %s is marked as fuzzy, skippingzerror: %s:%d: %szcompiling catalog %s to %sÚwb)r])rZr\ÚappendÚosÚpathÚjoinrYÚlistdirÚexistsr[rÚ	enumerateÚopenrrUr'ÚstringrbrÚinfoÚfuzzyr]ÚcheckrcÚlinenor)r6rXÚpo_filesZmo_filesr\Úpo_fileZcatalogs_and_errorsÚidxZmo_fileÚinfilerdZ
translatedÚmessageÚ
percentageZcatalog_errorsrercÚoutfiler!r!r"r`Åsn

 zcompile_catalog._run_domain)rCrDrE)rFrGrH)rIrJrK)rLrMrN)rOrPrQ)rRrSrT)rUNrV)r9r:r;Ú__doc__ÚdescriptionÚuser_optionsr>r0r^rfr`r!r!r!r"rB‡s*		rBcs‡fdd„}|S)zO
    Build a directory_filter function based on a list of ignore patterns.
    cs$tjj|ƒ‰t‡fdd„ˆDƒƒS)Nc3s|]}tjˆ|ƒVqdS)N)Úfnmatch)rZignore_pattern)Úbasenamer!r"r#szG_make_directory_filter.<locals>.cli_directory_filter.<locals>.<genexpr>)rlrmrƒÚany)Údirname)Úignore_patterns)rƒr"Úcli_directory_filters
z4_make_directory_filter.<locals>.cli_directory_filterr!)r†r‡r!)r†r"Ú_make_directory_filtersrˆc@s”eZdZdZdZdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`gZd	dddddd+gZd6ZdaZdbdcddded>œZ	d?dfiZ
dCdD„ZdEdF„ZdGdH„Z
dIdJ„ZdS)gÚextract_messagesaÂMessage extraction 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 extract_messages

        setup(
            ...
            cmdclass = {'extract_messages': extract_messages}
        )
    z1extract localizable strings from the project codeúcharset=Nú3charset to use in the output file (default "utf-8")ú	keywords=Úkúispace-separated list of keywords to look for in addition to the defaults (may be repeated multiple times)úno-default-keywordsú#do not include the default keywordsú
mapping-file=ÚFú&path to the mapping configuration fileúno-locationú>do not include location comments with filename and line numberú
add-location=úðlocation 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-headerú'do not include msgid "" entry in headerúoutput-file=rMúname of the output fileúwidth=Úwú"set output line width (default 76)úno-wrapúVdo not break long message lines, longer than the output line width, into several linesúsort-outputú&generate sorted output (default False)úsort-by-fileú,sort output by file location (default False)úmsgid-bugs-address=úset report address for msgidúcopyright-holder=úset copyright holder in outputúproject=úset project name in outputúversion=úset project version in outputú
add-comments=Úcúuplace comment block with TAG (or those preceding keyword lines) in output file. Separate multiple TAGs with commas(,)ústrip-commentsr ú)strip the comment TAGs from the comments.úinput-paths=úofiles or directories that should be scanned for messages. Separate multiple files or directories with commas(,)úinput-dirs=ú@alias for input-paths (does allow files as well as directories).úignore-dirs=úwPatterns for directories to ignore when scanning for messages. Separate multiple patterns with spaces (default ".* ._")úheader-comment=úheader comment for the catalogzinput-pathsúadd-commentsÚkeywordsúignore-dirsú	--keywordú	--mappingú--outputú--strip-comment-tags)r»zmapping-filezoutput-filezstrip-commentszadd-locationÚfullÚfileÚnevercCsŽd|_d|_d|_d|_d|_d|_d|_d|_d|_d|_	d|_
d|_d|_d|_
d|_d|_d|_d|_d|_d|_d|_d|_d|_dS)Nzutf-8FT)Úcharsetr»Úno_default_keywordsÚmapping_fileÚno_locationÚadd_locationÚomit_headerr[Ú
input_dirsÚinput_pathsÚwidthÚno_wrapÚsort_outputÚsort_by_fileÚmsgid_bugs_addressÚcopyright_holderÚprojectÚversionÚadd_commentsÚstrip_commentsÚinclude_linenoÚignore_dirsÚheader_comment)r6r!r!r"r0vs.z#extract_messages.initialize_optionscCsè|jr|js|j|_ntdƒ‚|jr*i}ntjƒ}|jtt|j	ƒƒƒ||_	|j	sZtdƒ‚|j
shtdƒ‚|jr||jr|tdƒ‚|jr”|jr”d|_n|jdk	rªt
|jƒ|_|jr¾|jr¾tdƒ‚|jrât|jtƒràtjd|jƒ|_n8|jdk	rtjdd	„|jjpfDƒƒjƒ|_ng|_|js*td
ƒ‚x*|jD] }tjj|ƒs2td|ƒ‚q2Wt|jpbfdƒ|_|jrš|js†|jjƒ|_|jsš|jj ƒ|_|j!d
kr®d|_"n|j!dkrÀd|_#t|j$ƒ}|rÞt%|j$ƒ|_&nd|_&dS)Nz1input-dirs and input-paths are mutually exclusivez=you must specify new keywords if you disable the default oneszno output file specifiedz0'--no-wrap' and '--width' are mutually exclusiveéLz;'--sort-output' and '--sort-by-file' are mutually exclusivez,\s*cSsg|]}|jddƒd‘qS)Ú.r_r)r)rrr!r!r"ú
<listcomp>»sz5extract_messages.finalize_options.<locals>.<listcomp>z'no input files or directories specifiedzInput path: %s does not existú,rÃTrÂF)'rÊrËrrÅrÚcopyÚupdateÚparse_keywordsr*r»r[rÍrÌÚintrÎrÏr$r%Úrerr/ÚdictÚfromkeysÚpackagesÚkeysrlrmrprÔrÒÚget_namerÓÚget_versionrÈrÇrÖr×rˆÚdirectory_filter)r6r»rmr×r!r!r"r^sh


z!extract_messages.finalize_optionscsLˆjƒ}tˆjdƒ,}tˆjˆjˆjˆjˆjˆj	p6t
d}xÌ|D]Ä\‰}}‡‡fdd„}tjj
ˆƒrŒtjƒ}tˆ|||ˆjˆjˆj|ƒ}n tˆ||ˆjˆj|ˆjˆjd}xX|D]P\}	}
}}}
tjj
ˆƒrÒ|	}ntjjtjjˆ|	ƒƒ}|j|d||
fg||
dq²WqBWˆjjdˆjƒt||ˆjˆjˆjˆjˆjˆj dWdQRXdS)	Nrj)rÒrÓrÐrÑrÄrØcsl|dkrdStjjˆƒrˆ}ntjjtjjˆ|ƒƒ}d}|rXddjdd„|jƒDƒƒ}ˆjjd||ƒdS)NÚignoreÚz (%s)z, cSsg|]\}}d||f‘qS)z%s="%s"r!)rrÚvr!r!r"rÛõsz:extract_messages.run.<locals>.callback.<locals>.<listcomp>zextracting messages from %s%s)rlrmÚisfileÚnormpathrnrarrt)ÚfilenameÚmethodÚoptionsÚfilepathZoptstr)rmr6r!r"Úcallbackæsz&extract_messages.run.<locals>.callback)r»Zcomment_tagsròZstrip_comment_tagsrè)Z
auto_commentsÚcontextzwriting PO template file to %s)rÌrÇrÉrÎrÏrÖ)!Ú
_get_mappingsrrr[r
rÒrÓrÐrÑrÄrØrrlrmrìÚgetcwdrr»rÔrÕrrèrírnÚaddrrtrrÌrÇrÉrÎrÏrÖ)r6Úmappingsr~rdÚ
method_mapÚoptions_mapròZcurrent_dirZ	extractedrîrwr|Úcommentsrórñr!)rmr6r"rfÛsH


zextract_messages.runcCsg}|jrNt|jƒ}t|ƒ\}}WdQRXxÒ|jD]}|j|||fƒq4Wn²t|jddƒrà|jj}xš|jƒD]l\}}t	|t
ƒr’tt|ƒƒ\}}n8gi}}x,|D]$\}}	}
|j||	fƒ|
pÀi||<q¢W|j|||fƒqnWn x|jD]}|j|tifƒqèW|S)NÚmessage_extractors)
rÆrrÚ
parse_mappingrËrkÚgetattrr/rûrar$r%rr
)r6r÷ÚfileobjrørùrmrûÚmappingÚpatternrïrðr!r!r"rôs&

zextract_messages._get_mappings)rŠNr‹)rŒrrŽ)rNr)r‘r’r“)r”Nr•)r–Nr—)r˜Nr™)ršrMr›)rœrrž)rŸNr )r¡Nr¢)r£Nr¤)r¥Nr¦)r§Nr¨)r©Nrª)r«Nr¬)r­r®r¯)r°r r±)r²Nr³)r´Nrµ)r¶Nr·)r¸Nr¹)rºr»r¼)r½)r¾)r¿)rÀ)rÁrÂrÃ)r9r:r;rr€rr>r<r=r?r@r0r^rfrôr!r!r!r"r‰sz

L?r‰cCs"|dkst‚t|tƒstdƒ‚dS)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
    rûzDthe value of the "message_extractors" parameter must be a dictionaryN)r,r$râr)r7ÚnameÚvaluer!r!r"Úcheck_message_extractors6s	
rc	@sDeZdZdZdZddd d!d"d#d$gZdgZdd„Zdd„Zdd„Z	dS)%Úinit_cataloga¾New 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údomain=rDú&domain of PO file (default 'messages')úinput-file=rJúname of the input fileúoutput-dir=rGúpath to output directoryúoutput-file=rMúQname of the output file (default '<output_dir>/<locale>/LC_MESSAGES/<domain>.po')úlocale=rPú$locale for the new localized catalogúwidth=rú"set output line width (default 76)úno-wrapNúVdo not break long message lines, longer than the output line width, into several linescCs.d|_d|_d|_d|_d|_d|_d|_dS)NrWF)Ú
output_dirr[rZr\rXrÍrÌ)r6r!r!r"r0kszinit_catalog.initialize_optionscCs
|jstdƒ‚|jstdƒ‚ytj|jƒ|_Wn,tk
rZ}zt|ƒ|‚WYdd}~XnX|jrt|jrttdƒ‚|js˜t	j
j|j|jd|jdƒ|_t	j
j
t	j
j|jƒƒsÂt	jt	j
j|jƒƒ|jrÖ|jrÖtdƒ‚|jrî|jrîd|_n|jdk	rt|jƒ|_dS)Nzyou must specify the input filez-you must provide a locale for the new catalogz%you must specify the output directoryrgz.poz0'--no-wrap' and '--width' are mutually exclusiverÙ)rZrr\rÚparseÚ_localer	r[rrlrmrnrXrpr…ÚmakedirsrÍrÌrà)r6Úer!r!r"r^ts*zinit_catalog.finalize_optionscCs€|jjd|j|jƒt|jdƒ}t||jd}WdQRX|j|_tj	t
ƒ|_d|_t|jdƒ}t
|||jdWdQRXdS)Nzcreating catalog %s based on %srh)r\Frj)rÌ)rrtr[rZrrrr\rrÚnowrÚ
revision_daterurrÌ)r6r{rdr~r!r!r"rfŽszinit_catalog.run)rrDr)rrJr)r	rGr
)rrMr)r
rPr)rrr)rNr)
r9r:r;rr€rr>r0r^rfr!r!r!r"rGs(
	rc@s`eZdZdZdZd0d1d2d3d4d5d6d7d8d9d:d;d<d=gZddd'd(dd#d!d)gZd*d+„Zd,d-„Zd.d/„Z	dS)>Úupdate_catalogaÔCatalog 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údomain=rDú&domain of PO file (default 'messages')úinput-file=rJúname of the input fileúoutput-dir=rGú.path to base directory containing the catalogsúoutput-file=rMúQname of the output file (default '<output_dir>/<locale>/LC_MESSAGES/<domain>.po')úomit-headerNú%do not include msgid  entry in headerúlocale=rPú locale of the catalog to compileúwidth=rú"set output line width (default 76)úno-wrapúVdo not break long message lines, longer than the output line width, into several linesúignore-obsolete=ú1whether to omit obsolete messages from the outputú
init-missing=ú6if any output files are missing, initialize them firstúno-fuzzy-matchingÚNúdo not use fuzzy matchingúupdate-header-commentúupdate target header commentÚpreviousú+keep previous msgids of translated messagesúcheck=ú‘don't update the catalog, just return the status. Return code 0 means nothing would change. Return code 1 means that the catalog would be updatedzignore-obsoletezinit-missingrvcCsXd|_d|_d|_d|_d|_d|_d|_d|_d|_d|_	d|_
d|_d|_d|_
dS)NrWF)rXrZrr[rÉr\rÌrÍÚignore_obsoleteÚinit_missingÚno_fuzzy_matchingÚupdate_header_commentr4rv)r6r!r!r"r0Úsz!update_catalog.initialize_optionscCsð|jstdƒ‚|jr&|jr&tdƒ‚|jr<|jr<tdƒ‚|jr’|jsPtdƒ‚ytj|jƒ|_Wq˜t	k
rŽ}zt|ƒ|‚WYdd}~Xq˜Xnd|_|j
r¬|jr¬tdƒ‚|j
rÄ|jrÄd|_n|jdk	rÚt|jƒ|_|j
rì|jrìd|_dS)Nzyou must specify the input filez-you must specify the output file or directoryzyou must specify the localez?you must specify the locale for the init-missing option to workz0'--no-wrap' and '--width' are mutually exclusiverÙF)rZrr[rr\r9rrrr	rÍrÌràr:r4)r6rr!r!r"r^ês.
zupdate_catalog.finalize_optionsc;Cs|i}g}|jsŠ|jr>|j|jtjj|j|jd|jdƒfƒqœx\tj|jƒD]8}tjj|j|d|jdƒ}tjj	|ƒrL|j||fƒqLWn|j|j|jfƒ|s¨t
dƒ‚|j}|sÌtjjtjj|j
ƒƒd}t|j
dƒ}t|ƒ}WdQRXx|D]\}}|jrštjj	|ƒrš|jr(d||<qô|jjd||j
ƒt|j
dƒ}t||jd}	WdQRX|j|	_tjtƒ|	_d|	_t|d	ƒ}
t|
|	ƒWdQRX|jjd
||j
ƒt|dƒ}t|||d}	WdQRX|	j||j|jdtjjtjj|ƒtj ƒtjj|ƒƒ}y6t|d	ƒ"}t||	|j!|j"|j#|j$d
WdQRXWntj%|ƒ‚YnX|jrÀt|dƒ}
t|
ƒ}WdQRXt|dƒ}t|ƒ}WdQRX|j|_|j&|ƒ||<tj%|ƒqôytj'||ƒWqôt(k
rtj%|ƒt)j*||ƒtj%|ƒYqôXqôW|jrxx:|j+ƒD].\}}|r<|jjd|ƒn|jj,d|ƒqWt-|j.ƒƒsht/dƒ‚n|jjdƒdSdS)Nrgz.pozno message catalogs foundrrhFzcreating catalog %s based on %s)r\rjzupdating catalog %s based on %s)r\rX)r;)rÉr8Zinclude_previousrÌzCatalog %s is up to date.zCatalog %s is out of date.zSome catalogs are out of date.z All the catalogs are up-to-date.)0r[r\rkrlrmrnrrXrorprÚsplitextrƒrZrrrr9rvrrtrrrrrrurrÞr:r;r…ÚtempfileÚ
gettempprefixrÉr8r4rÌÚremoveZis_identicalÚrenameÚOSErrorÚshutilrÝraÚwarningr+Úvaluesr)r6Zcheck_statusrxr\ryrXr{Útemplaterîrdr~ZtmpnameZtmpfileZorigfileZoriginal_catalogÚnewfileZupdated_catalogZ
up_to_dater!r!r"rf	sœ




zupdate_catalog.run)rrDr)rrJr)rrGr )r!rMr")r#Nr$)r%rPr&)r'rr()r)Nr*)r+Nr,)r-Nr.)r/r0r1)r2Nr3)r4Nr5)r6Nr7)
r9r:r;rr€rr>r0r^rfr!r!r!r"r sHrc@s^eZdZdZdZdeZdddddœZee	e
edœZd	Z
dd
d„Zdd
„Zdd„Zdd„Zd	S)ÚCommandLineInterfacez™Command-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)ÚcompileÚextractÚinitrÞNcCsn|dkrtj}tj|jd|jd|_|jjƒ|j|j_	|jj
ddddd	|jj
d
ddd
tjdd|jj
dddd
tj
dd|jjdtjd|jj|dd…ƒ\}}|j|jƒ|jrtjƒ}tdd„|Dƒƒ}|jƒd|d}x(|D] }tj|ƒ}t|||jfƒqôWdS|s.|jjdƒ|d}	|	|jkrR|jjd|	ƒ|j|	|dd…ƒ}
|
jƒS)z{Main entry point of the command-line interface.

        :param argv: list of arguments passed on the command-line
        NÚcommandú[args])ÚusagerÓz--list-localesÚlist_localesÚ
store_truez print all known locales and exit)ÚdestÚactionr4z-vz	--verboseÚstore_constÚloglevelzprint as much as possible)rQrPÚconstr4z-qz--quietzprint as little as possibleF)rNrSr_css|]}t|ƒVqdS)N)rb)rÚ
identifierr!r!r"r#ªsz+CommandLineInterface.run.<locals>.<genexpr>z
%%-%ds %%srzQno valid command or option passed. Try the -h/--help option for more information.zunknown command "%s")rKrL) ÚsysÚargvÚoptparseÚOptionParserrMrÓÚparserÚdisable_interspersed_argsÚ_helpÚ
print_helpÚ
add_optionÚloggingÚDEBUGÚERRORÚset_defaultsÚINFOÚ
parse_argsÚ_configure_loggingrSrNrZlocale_identifiersÚmaxÚsortrrÚprintZenglish_namercÚcommandsÚ_configure_commandrf)r6rWrðÚargsZidentifiersÚlongestÚformatrUr\ÚcmdnameÚcmdinstr!r!r"rfsD




zCommandLineInterface.runcCs^t|_|jj|ƒ|jjr(|jjd}ntjƒ}|jj|ƒ|j|ƒtjdƒ}|j|ƒdS)Nrz%(message)s)rÚsetLevelÚhandlersr_Ú
StreamHandlerÚ
addHandlerÚ	FormatterÚsetFormatter)r6rSÚhandlerÚ	formatterr!r!r"re½s

z'CommandLineInterface._configure_loggingcCspt|jjƒƒtdƒtdd„|jDƒƒ}dtd|dƒ}t|jjƒƒ}x |D]\}}t|||fƒqPWdS)Nz	commands:css|]}t|ƒVqdS)N)rb)rrKr!r!r"r#Ïsz-CommandLineInterface._help.<locals>.<genexpr>z  %%-%ds %%sér_)rhrZÚformat_helprfriÚsortedra)r6rlrmrirr€r!r!r"r\ÌszCommandLineInterface._helpcCsÔ|j|}|ƒ}|jr|j|_t|tƒs,t‚|jƒtj|j|df|j	|d}t
|dfƒ}xà|jD]Ö\}}}	|jdƒ}
t
||
j
ddƒƒ}d|
g}|r¨|jd|ƒ|j|jj|
fƒƒ|jj|
d	ƒ}
|
|kræ|jd
|
7_qf|
|jkr|j|d|	dœŽqf|
|jkr(|j|d
|	|
dœŽqf|j||	||
dœŽqfW|j|ƒ\}}|rht||j
ddƒ|ƒx&t|ƒjƒD]\}}t|||ƒqvWy|jƒWn2tk
rÎ}z|jt|ƒƒWYd	d	}~XnX|S)zB
        :type cmdname: str
        :type argv: list[str]
        rê)rMr€r<ú=ú-Ú_z--%sz-%sNz<%s>rO)rQr4rk)rQr4Úchoices)r4Údefaultr~)Úcommand_classesrr$rr,r0rXrYrMrirýrrÚreplacerkr)r?Úgetr@r>r^r=rdÚsetattrÚvarsraÚensure_finalizedrrcr%)r6rnrWÚcmdclassrorZr<ÚlongÚshortr4rrÚstrsr~rðrkÚkeyrÚerrr!r!r"rjÕsF


 z'CommandLineInterface._configure_command)N)r9r:r;rrMÚVERSIONrÓrirBr‰rrr€rrfrer\rjr!r!r!r"rGts 
0	rGcCstƒjtjƒS)N)rGrfrVrWr!r!r!r"Úmainsrc
CsÐi}g}i}tƒ}t|jƒ|_|j||ƒxb|jƒD]V}|dkrPt|j|ƒƒ}q4dd„|jddƒDƒ\}}|j||fƒt|j|ƒƒ||<q4W|rÈx4t	|ƒD](\}	\}}||kr¸||}||f||	<qœW||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`
    Ú
extractorscss|]}|jƒVqdS)N)r)rÚpartr!r!r"r#Gsz parse_mapping.<locals>.<genexpr>ú:r_)
rrÚ	_sectionsÚ	read_fileÚsectionsrârarrkrq)
rþrîrŽrørùrZÚsectionrïrrzr!r!r"rü
s$1rücCs¢i}x˜|D]}d|kr&|jdƒ\}}n
|d}}||kr
|r’g}xH|jdƒD]:}|ddkrx|jt|dd…ƒdfƒqL|jt|ƒƒqLWt|ƒ}|||<q
W|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NrÜr_r®éÿÿÿÿr•)rrkràr()Ústringsr»rsÚfuncnameÚindicesZindsÚxr!r!r"rßTs

rßÚ__main__)N)N)Drr‚r_rXrlrárBrVr=ÚcollectionsrÚconfigparserrrÚiorrrrŒrrZ
babel.corer	Zbabel.messages.catalogr
rZbabel.messages.extractrr
rrZbabel.messages.mofilerZbabel.messages.pofilerrZ
babel.utilrÚ	getLoggerrÚ
setuptoolsrZ_CommandrAZsetuptools.errorsrrrÚImportErrorÚ	ExceptionÚ	distutilsÚ
distutils.cmdZdistutils.errorsrrrr*rBrˆr‰rrrrGrrürßr9r!r!r!r"Ú<module>	sf

*)YU
J