changeset 12:a2c54ef107c2

* Removed pkg_resources/setuptools requirement from various places. * Fixed copyright year in a couple of file headers. * Some cleanup.
author cmlenz
date Thu, 31 May 2007 08:38:54 +0000
parents 1c9f6e203f6a
children b6c0de43fa40
files babel/__init__.py babel/catalog/extract.py babel/catalog/frontend.py babel/catalog/tests/__init__.py babel/catalog/tests/extract.py babel/catalog/tests/frontend.py babel/catalog/tests/pofile.py babel/core.py babel/dates.py babel/tests/__init__.py babel/tests/core.py babel/tests/dates.py babel/tests/numbers.py babel/tests/util.py doc/style/epydoc.css setup.py
diffstat 16 files changed, 138 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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):
--- 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()
--- 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
 
--- 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
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')
--- 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
--- 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]
+        <NumberPattern u'#,##0.###'>
+        
+        :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']
-        <DateTimeFormatPattern u'M/d/yy'>
+        <DateTimePattern u'M/d/yy'>
         >>> Locale('fr', 'FR').date_formats['long']
-        <DateTimeFormatPattern u'd MMMM yyyy'>
+        <DateTimePattern u'd MMMM yyyy'>
         
         :type: `dict`
         """)
@@ -344,20 +356,9 @@
         Locale patterns for time formatting.
         
         >>> Locale('en', 'US').time_formats['short']
-        <DateTimeFormatPattern u'h:mm a'>
+        <DateTimePattern u'h:mm a'>
         >>> Locale('fr', 'FR').time_formats['long']
-        <DateTimeFormatPattern u'HH:mm:ss z'>
-        
-        :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]
-        <NumberFormatPattern u'#,##0.###'>
+        <DateTimePattern u'HH:mm:ss z'>
         
         :type: `dict`
         """)
--- a/babel/dates.py
+++ b/babel/dates.py
@@ -116,9 +116,9 @@
     format.
     
     >>> get_date_format(locale='en_US')
-    <DateTimeFormatPattern u'MMM d, yyyy'>
+    <DateTimePattern u'MMM d, yyyy'>
     >>> get_date_format('full', locale='de_DE')
-    <DateTimeFormatPattern u'EEEE, d. MMMM yyyy'>
+    <DateTimePattern u'EEEE, d. MMMM yyyy'>
     
     :param format: the format to use, one of "full", "long", "medium", or
                    "short"
@@ -133,9 +133,9 @@
     format.
     
     >>> get_time_format(locale='en_US')
-    <DateTimeFormatPattern u'h:mm:ss a'>
+    <DateTimePattern u'h:mm:ss a'>
     >>> get_time_format('full', locale='de_DE')
-    <DateTimeFormatPattern u"H:mm' Uhr 'z">
+    <DateTimePattern u"H:mm' Uhr 'z">
     
     :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))
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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%; }
--- 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',
 
Copyright (C) 2012-2017 Edgewall Software