[Zope3-checkins] CVS: Zope3/src/zope/app/translation_files -
extract.py:1.15
Philipp von Weitershausen
philikon at philikon.de
Wed Dec 17 09:07:24 EST 2003
Update of /cvs-repository/Zope3/src/zope/app/translation_files
In directory cvs.zope.org:/tmp/cvs-serv8554/src/zope/app/translation_files
Modified Files:
extract.py
Log Message:
Divided the message id extraction machinery up into two files. The
extract module contains classes and functions and the i18nextract script
is the command utility using them.
=== Zope3/src/zope/app/translation_files/extract.py 1.14 => 1.15 ===
--- Zope3/src/zope/app/translation_files/extract.py:1.14 Wed Dec 17 05:06:12 2003
+++ Zope3/src/zope/app/translation_files/extract.py Wed Dec 17 09:06:54 2003
@@ -1,3 +1,4 @@
+#!/usr/bin/env python2.3
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
@@ -11,41 +12,22 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Program to extract internationalization markup from Python Code,
-Page Templates and ZCML.
+"""Extract message strings from python modules, page template files
+and ZCML files.
-This tool will extract all findable message strings from all
-internationalizable files in your Zope 3 product. It only extracts message ids
-of the specified domain. It defaults to the 'zope' domain and the zope.app
-package.
-
-Note: The Python Code extraction tool does not support domain registration, so
- that all message strings are returned for Python code.
-
-Usage: extract.py [options]
-Options:
- -h / --help
- Print this message and exit.
- -d / --domain <domain>
- Specifies the domain that is supposed to be extracted (i.e. 'zope')
- -p / --path <path>
- Specifies the package that is supposed to be searched
- (i.e. 'zope/app')
- -o dir
- Specifies a directory, relative to the package in which to put the
- output translation template.
+$Id$
"""
-__id__ = "$Id$"
import os, sys, fnmatch
-import getopt
import time
import tokenize
import traceback
from pygettext import safe_eval, normalize, make_escapes
-__meta_class__ = type
+from interfaces import IPOTEntry, IPOTMaker, ITokenEater
+from zope.interface import implements
+__meta_class__ = type
pot_header = '''\
##############################################################################
@@ -75,15 +57,10 @@
'''
-def usage(code, msg=''):
- # Python 2.1 required
- print >> sys.stderr, __doc__
- if msg:
- print >> sys.stderr, msg
- sys.exit(code)
-
class POTEntry:
- """This class represents a single message entry in the POT file."""
+ """This class represents a single message entry in the POT file.
+ """
+ implements(IPOTEntry)
def __init__(self, msgid, comments=None):
self.msgid = msgid
@@ -109,16 +86,16 @@
def __cmp__(self, other):
return cmp(self.comments, other.comments)
-
class POTMaker:
- """This class inserts sets of strings into a POT file."""
+ """This class inserts sets of strings into a POT file.
+ """
+ implements(IPOTMaker)
def __init__ (self, output_fn, path):
self._output_filename = output_fn
self.path = path
self.catalog = {}
-
def add(self, strings, base_dir=None):
for msgid, locations in strings.items():
if msgid == '':
@@ -130,7 +107,6 @@
if base_dir is not None:
filename = filename.replace(base_dir, '')
self.catalog[msgid].addLocationComment(filename, lineno)
-
def _getProductVersion(self):
# First, try to get the product version
@@ -145,13 +121,11 @@
else:
return 'Zope 3 (unknown version)'
-
def write(self):
-
file = open(self._output_filename, 'w')
- file.write(pot_header % {'time': time.ctime(),
+ file.write(pot_header % {'time': time.ctime(),
'version': self._getProductVersion()})
-
+
# Sort the catalog entries by filename
catalog = self.catalog.values()
catalog.sort()
@@ -162,10 +136,42 @@
file.close()
-
class TokenEater:
- """This is almost 100% taken from pygettext.py, except that I removed all
- option handling and output a dictionary."""
+ """This is almost 100% taken from pygettext.py, except that I
+ removed all option handling and output a dictionary.
+
+ >>> eater = TokenEater()
+ >>> make_escapes(0)
+
+ TokenEater eats tokens generated by the standard python module
+ tokenize.
+
+ >>> import tokenize
+ >>> from StringIO import StringIO
+
+ We feed it a (fake) file:
+
+ >>> file = StringIO("_('hello', 'buenos dias')")
+ >>> tokenize.tokenize(file.readline, eater)
+
+ The catalog of collected message ids contains our example
+
+ >>> catalog = eater.getCatalog()
+ >>> catalog
+ {u'hello': [(None, 1)]}
+
+ The key in the catalog is not a unicode string, it's a real
+ message id with a default value:
+
+ >>> msgid = catalog.keys()[0]
+ >>> msgid
+ u'hello'
+ >>> msgid.default
+ u'buenos dias'
+
+ Note that everything gets converted to unicode.
+ """
+ implements(ITokenEater)
def __init__(self):
self.__messages = {}
@@ -267,27 +273,6 @@
return catalog
-
-def app_dir():
- try:
- import zope.app
- except ImportError:
- # Couldn't import zope.app, need to add something to the Python
- # path
-
- # Get the path of the src
- path = os.path.abspath(os.path.dirname(sys.argv[0]))
- while not path.endswith('src'):
- path = os.path.dirname(path)
- sys.path.insert(0, path)
-
- import zope.app
-
- dir = os.path.dirname(zope.app.__file__)
-
- return dir
-
-
def find_files(dir, pattern, exclude=()):
files = []
@@ -297,12 +282,11 @@
if name not in exclude]
os.path.walk(dir, visit, files)
-
return files
-
def py_strings(dir, domain="zope"):
- """Retrieve all Python messages from dir that are in the domain."""
+ """Retrieve all Python messages from dir that are in the domain.
+ """
eater = TokenEater()
make_escapes(0)
for filename in find_files(dir, '*.py',
@@ -320,9 +304,9 @@
# XXX: No support for domains yet :(
return eater.getCatalog()
-
def zcml_strings(dir, domain="zope"):
- """Retrieve all ZCML messages from dir that are in the domain."""
+ """Retrieve all ZCML messages from dir that are in the domain.
+ """
from zope.app._app import config
import zope
dirname = os.path.dirname
@@ -331,9 +315,9 @@
context = config(site_zcml, execute=False)
return context.i18n_strings.get(domain, {})
-
def tal_strings(dir, domain="zope", include_default_domain=False):
- """Retrieve all TAL messages from dir that are in the domain."""
+ """Retrieve all TAL messages from dir that are in the domain.
+ """
# We import zope.tal.talgettext here because we can't rely on the
# right sys path until app_dir has run
from zope.tal.talgettext import POEngine, POTALInterpreter
@@ -368,60 +352,3 @@
for msgid, locations in catalog.items():
catalog[msgid] = map(lambda l: (l[0], l[1][0]), locations)
return catalog
-
-
-def main(argv=sys.argv):
- try:
- opts, args = getopt.getopt(
- sys.argv[1:],
- 'hd:p:o:',
- ['help', 'domain=', 'path='])
- except getopt.error, msg:
- usage(1, msg)
-
- domain = 'zope'
- path = app_dir()
- include_default_domain = True
- output_dir = None
- for opt, arg in opts:
- if opt in ('-h', '--help'):
- usage(0)
- elif opt in ('-d', '--domain'):
- domain = arg
- include_default_domain = False
- elif opt in ('-o', ):
- output_dir = arg
- elif opt in ('-p', '--path'):
- if not os.path.exists(arg):
- usage(1, 'The specified path does not exist.')
- path = arg
- # We might not have an absolute path passed in.
- if not path == os.path.abspath(path):
- cwd = os.getcwd()
- # This is for symlinks. Thanks to Fred for this trick.
- if os.environ.has_key('PWD'):
- cwd = os.environ['PWD']
- path = os.path.normpath(os.path.join(cwd, arg))
-
- # When generating the comments, we will not need the base directory info,
- # since it is specific to everyone's installation
- src_start = path.find('src')
- base_dir = path[:src_start]
-
- output_file = domain+'.pot'
- if output_dir:
- output_dir = os.path.join(path, output_dir)
- if not os.path.exists(output_dir):
- os.mkdir(output_dir)
- output_file = os.path.join(output_dir, output_file)
-
-
- maker = POTMaker(output_file, path)
- maker.add(py_strings(path, domain), base_dir)
- maker.add(zcml_strings(path, domain), base_dir)
- maker.add(tal_strings(path, domain, include_default_domain), base_dir)
- maker.write()
-
-
-if __name__ == '__main__':
- main()
More information about the Zope3-Checkins
mailing list