# HG changeset patch # User cmlenz # Date 1180600734 0 # Node ID 29ef15a6fd75395bb5c651fb23b9214ec1de1eb8 # Parent da3326ba1301985654212f14bfe75bcdbf1383d3 * Removed pkg_resources/setuptools requirement from various places. * Fixed copyright year in a couple of file headers. * Some cleanup. diff --git a/babel/__init__.py b/babel/__init__.py --- a/babel/__init__.py +++ b/babel/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -29,4 +29,7 @@ from babel.core import * __docformat__ = 'restructuredtext en' -__version__ = __import__('pkg_resources').get_distribution('Babel').version +try: + __version__ = __import__('pkg_resources').get_distribution('Babel').version +except ImportError: + pass diff --git a/babel/catalog/extract.py b/babel/catalog/extract.py --- a/babel/catalog/extract.py +++ b/babel/catalog/extract.py @@ -22,7 +22,6 @@ """ import os -from pkg_resources import working_set import sys from tokenize import generate_tokens, NAME, OP, STRING @@ -33,7 +32,7 @@ GROUP_NAME = 'babel.extractors' -KEYWORDS = { +DEFAULT_KEYWORDS = { '_': None, 'gettext': None, 'ngettext': (1, 2), @@ -49,8 +48,8 @@ } -def extract_from_dir(dirname, mapping=DEFAULT_MAPPING, keywords=KEYWORDS, - options=None): +def extract_from_dir(dirname, mapping=DEFAULT_MAPPING, + keywords=DEFAULT_KEYWORDS, options=None): """Extract messages from any source files found in the given directory. This function generates tuples of the form: @@ -80,8 +79,10 @@ :param dirname: the path to the directory to extract messages from :param mapping: a mapping of extraction method names to extended glob patterns - :param keywords: a list of keywords (i.e. function names) that should be - recognized as translation functions + :param keywords: a dictionary mapping keywords (i.e. names of functions + that should be recognized as translation functions) to + tuples that specify which of their arguments contain + localizable strings :param options: a dictionary of additional options (optional) :return: an iterator over ``(filename, lineno, funcname, message)`` tuples :rtype: ``iterator`` @@ -99,7 +100,8 @@ yield filename, line, func, key extracted_files[filename] = True -def extract_from_file(method, filename, keywords=KEYWORDS, options=None): +def extract_from_file(method, filename, keywords=DEFAULT_KEYWORDS, + options=None): """Extract messages from a specific file. This function returns a list of tuples of the form: @@ -108,8 +110,10 @@ :param filename: the path to the file to extract messages from :param method: a string specifying the extraction method (.e.g. "python") - :param keywords: a list of keywords (i.e. function names) that should be - recognized as translation functions + :param keywords: a dictionary mapping keywords (i.e. names of functions + that should be recognized as translation functions) to + tuples that specify which of their arguments contain + localizable strings :param options: a dictionary of additional options (optional) :return: the list of extracted messages :rtype: `list` @@ -120,7 +124,7 @@ finally: fileobj.close() -def extract(method, fileobj, keywords=KEYWORDS, options=None): +def extract(method, fileobj, keywords=DEFAULT_KEYWORDS, options=None): """Extract messages from the given file-like object using the specified extraction method. @@ -143,28 +147,32 @@ :param method: a string specifying the extraction method (.e.g. "python") :param fileobj: the file-like object the messages should be extracted from - :param keywords: a list of keywords (i.e. function names) that should be - recognized as translation functions + :param keywords: a dictionary mapping keywords (i.e. names of functions + that should be recognized as translation functions) to + tuples that specify which of their arguments contain + localizable strings :param options: a dictionary of additional options (optional) :return: the list of extracted messages :rtype: `list` :raise ValueError: if the extraction method is not registered """ + from pkg_resources import working_set + for entry_point in working_set.iter_entry_points(GROUP_NAME, method): func = entry_point.load(require=True) m = [] for lineno, funcname, messages in func(fileobj, keywords.keys(), options=options or {}): if isinstance(messages, (list, tuple)): - indices = keywords[funcname] msgs = [] - for indice in indices: - msgs.append(messages[indice-1]) + for index in keywords[funcname]: + msgs.append(messages[index - 1]) messages = tuple(msgs) if len(messages) == 1: messages = messages[0] yield lineno, funcname, messages return + raise ValueError('Unknown extraction method %r' % method) def extract_genshi(fileobj, keywords, options): diff --git a/babel/catalog/frontend.py b/babel/catalog/frontend.py --- a/babel/catalog/frontend.py +++ b/babel/catalog/frontend.py @@ -20,7 +20,7 @@ import sys from babel import __version__ as VERSION -from babel.catalog.extract import extract_from_dir, KEYWORDS +from babel.catalog.extract import extract_from_dir, DEFAULT_KEYWORDS from babel.catalog.pofile import write_po __all__ = ['extract_messages', 'main'] @@ -53,7 +53,7 @@ 'space-separated list of keywords to look for in addition to the ' 'defaults'), ('no-default-keywords', None, - 'do not include the default keywords defined by Babel'), + 'do not include the default keywords'), ('no-location', None, 'do not include location comments with filename and line number'), ('omit-header', None, @@ -61,28 +61,27 @@ ('output-file=', 'o', 'name of the output file'), ] - boolean_options = ['no-location', 'omit-header', 'no-default-keywords'] + boolean_options = ['no-default-keywords', 'no-location', 'omit-header'] def initialize_options(self): self.charset = 'utf-8' - self.keywords = KEYWORDS + self.keywords = DEFAULT_KEYWORDS.copy() + self.no_default_keywords = False self.no_location = False self.omit_header = False self.output_file = None self.input_dirs = None - self.no_default_keywords = False def finalize_options(self): if not self.input_dirs: self.input_dirs = dict.fromkeys([k.split('.',1)[0] for k in self.distribution.packages ]).keys() + if self.no_default_keywords: + self.keywords = {} if isinstance(self.keywords, basestring): - new_keywords = [k.strip() for k in self.keywords.split()] - self.keywords = build_gettext_functions( - new_keywords, - dont_include_default=self.no_default_keywords - ) + new_keywords = parse_keywords(self.keywords.split()) + self.keywords.update(new_keywords) def run(self): outfile = open(self.output_file, 'w') @@ -102,25 +101,6 @@ finally: outfile.close() -def build_gettext_functions(func_list=[], dont_include_default=False): - """Build the gettext function to parse.""" - if dont_include_default: - func_dict = {} - else: - func_dict = KEYWORDS - for func in func_list: - if func.find(':') != -1: - func_name, func_args = func.split(':') - else: - func_name, func_args = func, None - if not func_dict.has_key(func_name): - if func_args: - str_indexes = [(int(x) -1 ) for x in func_args.split(',')] - else: - str_indexes = None - func_dict[func_name] = str_indexes - return func_dict - def main(argv=sys.argv): """Command-line interface. @@ -159,14 +139,15 @@ outfile = open(options.output, 'w') else: outfile = sys.stdout - - if options.no_default_keywords and not options.keywords: - parser.error("you must pass keywords to disable the default ones") - elif options.no_default_keywords and options.keywords: - keywords = build_gettext_functions(options.keywords, - dont_include_default=options.no_default_keywords) - else: - keywords = build_gettext_functions() + + keywords = DEFAULT_KEYWORDS.copy() + if options.no_default_keywords: + if not options.keywords: + parser.error('you must specify new keywords if you disable the ' + 'default ones') + keywords = {} + if options.keywords: + keywords.update(parse_keywords(options.keywords)) try: messages = [] @@ -184,5 +165,27 @@ if options.output: outfile.close() +def parse_keywords(strings=[]): + """Parse keywords specifications from the given list of strings. + + >>> kw = parse_keywords(['_', 'dgettext:2', 'dngettext:2,3']) + >>> for keyword, indices in sorted(kw.items()): + ... print (keyword, indices) + ('_', None) + ('dgettext', (2,)) + ('dngettext', (2, 3)) + """ + keywords = {} + for string in strings: + if ':' in string: + funcname, indices = string.split(':') + else: + funcname, indices = string, None + if funcname not in keywords: + if indices: + indices = tuple([(int(x)) for x in indices.split(',')]) + keywords[funcname] = indices + return keywords + if __name__ == '__main__': main() diff --git a/babel/catalog/tests/__init__.py b/babel/catalog/tests/__init__.py --- a/babel/catalog/tests/__init__.py +++ b/babel/catalog/tests/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -14,9 +14,10 @@ import unittest def suite(): - from babel.catalog.tests import extract, pofile + from babel.catalog.tests import extract, frontend, pofile suite = unittest.TestSuite() suite.addTest(extract.suite()) + suite.addTest(frontend.suite()) suite.addTest(pofile.suite()) return suite diff --git a/babel/catalog/tests/extract.py b/babel/catalog/tests/extract.py --- a/babel/catalog/tests/extract.py +++ b/babel/catalog/tests/extract.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/babel/catalog/tests/frontend.py b/babel/catalog/tests/frontend.py new file mode 100644 --- /dev/null +++ b/babel/catalog/tests/frontend.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://babel.edgewall.org/wiki/License. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://babel.edgewall.org/log/. + +import doctest +import unittest + +from babel.catalog import frontend + +def suite(): + suite = unittest.TestSuite() + suite.addTest(doctest.DocTestSuite(frontend)) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/babel/catalog/tests/pofile.py b/babel/catalog/tests/pofile.py --- a/babel/catalog/tests/pofile.py +++ b/babel/catalog/tests/pofile.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/babel/core.py b/babel/core.py --- a/babel/core.py +++ b/babel/core.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -13,8 +13,8 @@ """Core locale representation and locale data access gateway.""" +import os import pickle -from pkg_resources import resource_filename try: import threading except ImportError: @@ -129,7 +129,8 @@ def _data(self): if self.__data is None: - filename = resource_filename(__name__, 'localedata/%s.dat' % self) + filename = os.path.join(os.path.dirname(__file__), + 'localedata/%s.dat' % self) fileobj = open(filename, 'rb') try: self.__data = pickle.load(fileobj) @@ -219,6 +220,17 @@ :type: `dict` """) + def decimal_formats(self): + return self._data['decimal_formats'] + decimal_formats = property(decimal_formats, doc="""\ + Locale patterns for decimal number formatting. + + >>> Locale('en', 'US').decimal_formats[None] + + + :type: `dict` + """) + #{ Calendar Information and Date Formatting def periods(self): @@ -331,9 +343,9 @@ Locale patterns for date formatting. >>> Locale('en', 'US').date_formats['short'] - + >>> Locale('fr', 'FR').date_formats['long'] - + :type: `dict` """) @@ -344,20 +356,9 @@ Locale patterns for time formatting. >>> Locale('en', 'US').time_formats['short'] - + >>> Locale('fr', 'FR').time_formats['long'] - - - :type: `dict` - """) - - def decimal_formats(self): - return self._data['decimal_formats'] - decimal_formats = property(decimal_formats, doc="""\ - Locale patterns for decimal number formatting. - - > Locale('en', 'US').decimal_formats[None] - + :type: `dict` """) diff --git a/babel/dates.py b/babel/dates.py --- a/babel/dates.py +++ b/babel/dates.py @@ -116,9 +116,9 @@ format. >>> get_date_format(locale='en_US') - + >>> get_date_format('full', locale='de_DE') - + :param format: the format to use, one of "full", "long", "medium", or "short" @@ -133,9 +133,9 @@ format. >>> get_time_format(locale='en_US') - + >>> get_time_format('full', locale='de_DE') - + :param format: the format to use, one of "full", "long", "medium", or "short" @@ -204,7 +204,7 @@ raise NotImplementedError -class DateTimeFormatPattern(object): +class DateTimePattern(object): def __init__(self, pattern, format): self.pattern = pattern @@ -327,7 +327,7 @@ :param pattern: the formatting pattern to parse """ - if type(pattern) is DateTimeFormatPattern: + if type(pattern) is DateTimePattern: return pattern result = [] @@ -384,4 +384,4 @@ elif charbuf: append_chars() - return DateTimeFormatPattern(pattern, u''.join(result)) + return DateTimePattern(pattern, u''.join(result)) diff --git a/babel/tests/__init__.py b/babel/tests/__init__.py --- a/babel/tests/__init__.py +++ b/babel/tests/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/babel/tests/core.py b/babel/tests/core.py --- a/babel/tests/core.py +++ b/babel/tests/core.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/babel/tests/dates.py b/babel/tests/dates.py --- a/babel/tests/dates.py +++ b/babel/tests/dates.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/babel/tests/numbers.py b/babel/tests/numbers.py --- a/babel/tests/numbers.py +++ b/babel/tests/numbers.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/babel/tests/util.py b/babel/tests/util.py --- a/babel/tests/util.py +++ b/babel/tests/util.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006 Edgewall Software +# Copyright (C) 2007 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which diff --git a/doc/style/epydoc.css b/doc/style/epydoc.css --- a/doc/style/epydoc.css +++ b/doc/style/epydoc.css @@ -47,6 +47,9 @@ table.summary { margin: .5em 0; } table.summary tr.table-header { background: #f7f7f0; } table.summary td.table-header { color: #666; font-weight: bold; } +table.summary th.group-header { background: #f7f7f0; color: #666; + font-size: 90%; font-weight: bold; text-align: left; +} table.summary th, table.summary td { border: 1px solid #d7d7d7; } table.summary th th, table.summary td td { border: none; } table.summary td.summary table td { color: #666; font-size: 90%; } diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -12,10 +12,14 @@ # individuals. For the exact contribution history, see the revision # history and logs, available at http://babel.edgewall.org/log/. +from distutils.cmd import Command import doctest from glob import glob import os -from setuptools import find_packages, setup, Command +try: + from setuptools import setup +except ImportError: + from distutils.core import setup import sys @@ -97,7 +101,7 @@ 'Programming Language :: Python', 'Topic :: Software Development :: Libraries :: Python Modules', ], - packages = find_packages(exclude=['tests']), + packages = ['babel', 'babel.catalog'], package_data = {'babel': ['localedata/*.dat']}, test_suite = 'babel.tests.suite',