[Zope3-checkins] CVS: Zope3/utilities - i18nextract.py:1.2

Philipp von Weitershausen philikon at philikon.de
Wed Dec 17 09:06:55 EST 2003


Update of /cvs-repository/Zope3/utilities
In directory cvs.zope.org:/tmp/cvs-serv8554/utilities

Modified Files:
	i18nextract.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/utilities/i18nextract.py 1.1 => 1.2 ===
--- Zope3/utilities/i18nextract.py:1.1	Wed Dec 17 02:59:34 2003
+++ Zope3/utilities/i18nextract.py	Wed Dec 17 09:06:54 2003
@@ -40,237 +40,17 @@
 $Id$
 """
 
-import os, sys, fnmatch
-import getopt
-import time
-import tokenize
-import traceback
-from pygettext import safe_eval, normalize, make_escapes
-
-__meta_class__ = type
-
-
-pot_header = '''\
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-msgid ""
-msgstr ""
-"Project-Id-Version: %(version)s\\n"
-"POT-Creation-Date: %(time)s\\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
-"Last-Translator: FULL NAME <EMAIL at ADDRESS>\\n"
-"Language-Team: Zope 3 Developers <zope3-dev at zope.org>\\n"
-"MIME-Version: 1.0\\n"
-"Content-Type: text/plain; charset=CHARSET\\n"
-"Content-Transfer-Encoding: ENCODING\\n"
-"Generated-By: zope/app/translation_files/extract.py\\n"
-
-'''
+import os, sys, fnmatch, getopt
+from zope.app.translation_files.extract import POTMaker, \
+     py_strings, tal_strings, zcml_strings
 
 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.
-    """
-
-    def __init__(self, msgid, comments=None):
-        self.msgid = msgid
-        self.comments = comments or ''
-
-    def addComment(self, comment):
-        self.comments += comment + '\n'
-
-    def addLocationComment(self, filename, line):
-        self.comments += '#: %s:%s\n' %(filename, line)
-
-    def write(self, file):
-        file.write(self.comments)
-        from zope.i18n.messageid import MessageID
-        if isinstance(self.msgid, MessageID) and \
-               self.msgid != self.msgid.default:
-            default = self.msgid.default.strip()
-            file.write('# Default: %s\n' % normalize(default))
-        file.write('msgid %s\n' % normalize(self.msgid))
-        file.write('msgstr ""\n')
-        file.write('\n')
-
-    def __cmp__(self, other):
-        return cmp(self.comments, other.comments)
-
-
-class POTMaker:
-    """This class inserts sets of strings into a POT file.
-    """
-    
-    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 == '':
-                continue
-            if msgid not in self.catalog:
-                self.catalog[msgid] = POTEntry(msgid)
-
-            for filename, lineno in locations:
-                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
-        fn = os.path.join(self.path, 'version.txt')
-        if os.path.exists(fn):
-            return open(fn, 'r').read().strip()
-        # Second, try to find a Zope version
-        import zope
-        fn = os.path.join(os.path.dirname(zope.__file__), 'version.txt')
-        if os.path.exists(fn):
-            return open(fn, 'r').read().strip()
-        else:
-            return 'Zope 3 (unknown version)'
-
-
-    def write(self):
-        file = open(self._output_filename, 'w')
-        file.write(pot_header % {'time': time.ctime(),
-                                 'version': self._getProductVersion()})
-        
-        # Sort the catalog entries by filename
-        catalog = self.catalog.values()
-        catalog.sort()
-
-        # Write each entry to the file
-        for entry in catalog:
-            entry.write(file)
-            
-        file.close()
-
-
-class TokenEater:
-    """This is almost 100% taken from pygettext.py, except that I
-    removed all option handling and output a dictionary.
-    """
-    
-    def __init__(self):
-        self.__messages = {}
-        self.__state = self.__waiting
-        self.__data = []
-        self.__lineno = -1
-        self.__freshmodule = 1
-        self.__curfile = None
-
-    def __call__(self, ttype, tstring, stup, etup, line):
-        self.__state(ttype, tstring, stup[0])
-
-    def __waiting(self, ttype, tstring, lineno):
-        if ttype == tokenize.NAME and tstring in ['_']:
-            self.__state = self.__keywordseen
-
-    def __suiteseen(self, ttype, tstring, lineno):
-        # ignore anything until we see the colon
-        if ttype == tokenize.OP and tstring == ':':
-            self.__state = self.__suitedocstring
-
-    def __suitedocstring(self, ttype, tstring, lineno):
-
-        # ignore any intervening noise
-        if ttype == tokenize.STRING:
-            self.__addentry(safe_eval(tstring), lineno, isdocstring=1)
-            self.__state = self.__waiting
-        elif ttype not in (tokenize.NEWLINE, tokenize.INDENT,
-                           tokenize.COMMENT):
-            # there was no class docstring
-            self.__state = self.__waiting
-
-    def __keywordseen(self, ttype, tstring, lineno):
-        if ttype == tokenize.OP and tstring == '(':
-            self.__data = []
-            self.__msgid = ''
-            self.__lineno = lineno
-            self.__state = self.__openseen
-        else:
-            self.__state = self.__waiting
-
-    def __openseen(self, ttype, tstring, lineno):
-        if ttype == tokenize.OP and tstring == ')':
-            # We've seen the last of the translatable strings.  Record the
-            # line number of the first line of the strings and update the list 
-            # of messages seen.  Reset state for the next batch.  If there
-            # were no strings inside _(), then just ignore this entry.
-            if self.__data or self.__msgid:
-                if self.__msgid:
-                    msgid = self.__msgid
-                    default = ''.join(self.__data)
-                else:
-                    msgid = ''.join(self.__data)
-                    default = None
-                self.__addentry(msgid, default)
-            self.__state = self.__waiting
-        elif ttype == tokenize.OP and tstring == ',':
-            self.__msgid = ''.join(self.__data)
-            self.__data = []
-        elif ttype == tokenize.STRING:
-            self.__data.append(safe_eval(tstring))
-
-    def __addentry(self, msg, default=None, lineno=None, isdocstring=0):
-        if lineno is None:
-            lineno = self.__lineno
-
-        if default is not None:
-            from zope.i18n.messageid import MessageID
-            msg = MessageID(msg, default=default)
-        entry = (self.__curfile, lineno)
-        self.__messages.setdefault(msg, {})[entry] = isdocstring
-
-    def set_filename(self, filename):
-        self.__curfile = filename
-        self.__freshmodule = 1
-
-    def getCatalog(self):
-        catalog = {}
-        # Sort the entries.  First sort each particular entry's keys, then
-        # sort all the entries by their first item.
-        reverse = {}
-        for k, v in self.__messages.items():
-            keys = v.keys()
-            keys.sort()
-            reverse.setdefault(tuple(keys), []).append((k, v))
-        rkeys = reverse.keys()
-        rkeys.sort()
-        for rkey in rkeys:
-            rentries = reverse[rkey]
-            rentries.sort()
-            for msgid, locations in rentries:
-                catalog[msgid] = []
-                
-                locations = locations.keys()
-                locations.sort()
-
-                for filename, lineno in locations:
-                    catalog[msgid].append((filename, lineno))
-
-        return catalog
-
-                    
 def app_dir():
     try:
         import zope.app
@@ -286,93 +66,9 @@
 
         import zope.app
 
-    return os.path.dirname(zope.app.__file__)
-
-
-def find_files(dir, pattern, exclude=()):
-    files = []
-
-    def visit(files, dirname, names):
-        files += [os.path.join(dirname, name)
-                  for name in fnmatch.filter(names, pattern)
-                  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.
-    """
-    eater = TokenEater()
-    make_escapes(0)
-    for filename in find_files(dir, '*.py', 
-                               exclude=('extract.py', 'pygettext.py')):
-        fp = open(filename)
-        try:
-            eater.set_filename(filename)
-            try:
-                tokenize.tokenize(fp.readline, eater)
-            except tokenize.TokenError, e:
-                print >> sys.stderr, '%s: %s, line %d, column %d' % (
-                    e[0], filename, e[1][0], e[1][1])
-        finally:
-            fp.close()            
-    # 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.
-    """
-    from zope.app._app import config
-    import zope
-    dirname = os.path.dirname
-    site_zcml = os.path.join(dirname(dirname(dirname(zope.__file__))),
-                             "site.zcml")
-    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.
-    """
-    # 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
-    from zope.tal.htmltalparser import HTMLTALParser
-    engine = POEngine()
-
-    class Devnull:
-        def write(self, s):
-            pass
-
-    for filename in find_files(dir, '*.pt'):
-        try:
-            engine.file = filename
-            p = HTMLTALParser()
-            p.parseFile(filename)
-            program, macros = p.getCode()
-            POTALInterpreter(program, macros, engine, stream=Devnull(),
-                             metal=False)()
-        except: # Hee hee, I love bare excepts!
-            print 'There was an error processing', filename
-            traceback.print_exc()
-
-    # See whether anything in the domain was found
-    if not engine.catalog.has_key(domain):
-        return {}
-    # We do not want column numbers.
-    catalog = engine.catalog[domain].copy()
-    # When the Domain is 'default', then this means that none was found;
-    # Include these strings; yes or no?
-    if include_default_domain:
-        catalog.update(engine.catalog['default'])
-    for msgid, locations in catalog.items():
-        catalog[msgid] = map(lambda l: (l[0], l[1][0]), locations)
-    return catalog
+    dir = os.path.dirname(zope.app.__file__)
 
+    return dir
 
 def main(argv=sys.argv):
     try:
@@ -418,14 +114,12 @@
         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