# HG changeset patch # User cmlenz # Date 1181175327 0 # Node ID 37bd476dafe4aeadca0b24a194615f8da0fde18d # Parent 22b90b3b161adf5ee597f62b8260aa98ea5a5553 Support a `message_extractors` keyword argument directly in `setup()`. Closes #4. diff --git a/babel/catalog/frontend.py b/babel/catalog/frontend.py --- a/babel/catalog/frontend.py +++ b/babel/catalog/frontend.py @@ -16,10 +16,11 @@ from ConfigParser import RawConfigParser from distutils import log from distutils.cmd import Command -from distutils.errors import DistutilsOptionError +from distutils.errors import DistutilsOptionError, DistutilsSetupError from optparse import OptionParser import os import re +from StringIO import StringIO import sys from babel import __version__ as VERSION @@ -27,7 +28,7 @@ DEFAULT_MAPPING from babel.catalog.pofile import write_po -__all__ = ['extract_messages', 'main'] +__all__ = ['extract_messages', 'check_message_extractors', 'main'] __docformat__ = 'restructuredtext en' @@ -112,6 +113,18 @@ method_map, options_map = parse_mapping(fileobj) finally: fileobj.close() + elif self.distribution.message_extractors: + message_extractors = self.distribution.message_extractors + if isinstance(message_extractors, basestring): + method_map, options_map = parse_mapping(StringIO( + message_extractors + )) + else: + method_map = {} + options_map = {} + for pattern, (method, options) in message_extractors.items(): + method_map[pattern] = method + options_map[pattern] = options else: method_map = DEFAULT_MAPPING options_map = {} @@ -142,6 +155,22 @@ finally: outfile.close() +def check_message_extractors(dist, name, value): + """Validate 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 + :see: `Adding setup() arguments + `_ + """ + assert name == 'message_extractors' + if not isinstance(value, (basestring, dict)): + raise DistutilsSetupError('the value of the "extract_messages" ' + 'parameter must be a string or dictionary') + def main(argv=sys.argv): """Command-line interface. @@ -234,7 +263,6 @@ def parse_mapping(fileobj, filename=None): """Parse an extraction method mapping from a file-like object. - >>> from StringIO import StringIO >>> buf = StringIO(''' ... # Python source files ... [python: foobar/**.py] diff --git a/doc/catalogs.txt b/doc/catalogs.txt --- a/doc/catalogs.txt +++ b/doc/catalogs.txt @@ -140,22 +140,26 @@ Lines that start with a ``#`` or ``;`` character are ignored and can be used for comments. Empty lines are also ignored, too. - ---------------------- -``setup.py`` Commands ---------------------- - -(TODO: overview) +.. note:: if you're performing message extraction using the command Babel + provides for integration into ``setup.py`` scripts (see below), you + can also provide this configuration in a different way, namely as a + keyword argument to the ``setup()`` function. -See `Distutils/Setuptools Integration `_ for more information. -------------------- -Command-line script -------------------- +---------- +Front-Ends +---------- -(TODO: overview) +Babel provides two different front-ends to access its functionality for working +with message catalogs: -See `Command-Line Interface `_ for more information. + * A `Command-line interface `_, and + * `Integeration with distutils/setuptools `_ + +Which one you choose depends on the nature of your project. For most modern +Python projects, the distutils/setuptools integration is probably more +convenient. + -------------------------- Writing Extraction Methods diff --git a/doc/setup.txt b/doc/setup.txt --- a/doc/setup.txt +++ b/doc/setup.txt @@ -46,19 +46,52 @@ --help (-h) show detailed help message Options for 'extract_messages' command: - --charset charset to use in the output - --keywords (-k) comma-separated list of keywords to look for in addition - to the defaults - --no-location do not write filename/lineno location comments - --output-file filename of the output PO file + --charset charset to use in the output file + --keywords (-k) space-separated list of keywords to look for in + addition to the defaults + --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 + --omit-header do not include msgid "" entry in header + --output-file (-o) name of the output file + --width (-w) set output line width (default 76) + --no-wrap do not break long message lines, longer than the + output line width, into several lines Running the command will produce a PO file:: - $ ./setup.py extract_messages --output-file webapp/locales/messages.pot + $ ./setup.py extract_messages --output-file foobar/locale/messages.pot running extract_messages - extracting messages from 'webapp' - extracting messages from 'webparts' - writing PO file to webapp/locales/messages.pot + extracting messages from foobar/__init__.py + extracting messages from foobar/core.py + ... + writing PO file to foobar/locale/messages.pot + + +Method Mapping +-------------- + +The mapping of file patterns to extraction methods (and options) can be +specified using a configuration file that is pointed to using the +``--mapping-file`` option shown above. Alternatively, you can configure the +mapping directly in ``setup.py`` using a keyword argument to the ``setup()`` +function: + +.. code-block:: python + + setup(... + + message_extractors = { + 'foobar/**.py': ('python', None), + 'foobar/**/templates/**.html': ('genshi', None), + 'foobar/**/templates/**.txt': ('genshi', { + 'template_class': 'genshi.template.text.TextTemplate' + }) + }, + + ... + ) Options @@ -67,14 +100,27 @@ As shown in the ``--help`` output above, the ``extract_messages`` command accepts the following options: -``--charset`` - The character set / encoding to use in the generated PO file. -``--keywords`` - A comma-separated list of keywords (function names) to look for in addition - to the default keywords -``--no-location`` - If this flag is set, location comments will not be included in the generated - PO file. -``--output-file`` or ``-o`` - The path to the PO file that should be generated - + +-----------------------------+----------------------------------------------+ + | Option | Description | + +=============================+==============================================+ + | ``--charset`` | charset to use in the output file | + +-----------------------------+----------------------------------------------+ + | ``--keywords`` (``-k``) | space-separated list of keywords to look for | + | | in addition to the defaults | + +-----------------------------+----------------------------------------------+ + | ``--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 | + +-----------------------------+----------------------------------------------+ + | ``--omit-header`` | do not include msgid "" entry in header | + +-----------------------------+----------------------------------------------+ + | ``--output-file`` (``-o``) | name of the output file | + +-----------------------------+----------------------------------------------+ + | ``--width`` (``-w``) | set output line width (default 76) | + +-----------------------------+----------------------------------------------+ + | ``--no-wrap`` | do not break long message lines, longer than | + | | the output line width, into several lines | + +-----------------------------+----------------------------------------------+ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -132,6 +132,9 @@ [distutils.commands] extract_messages = babel.catalog.frontend:extract_messages + [distutils.setup_keywords] + message_extractors = babel.catalog.frontend:check_message_extractors + [babel.extractors] genshi = babel.catalog.extract:extract_genshi python = babel.catalog.extract:extract_python