[Python-modules-commits] [python-kajiki] 01/05: New upstream version 0.7.0

Takaki Taniguchi takaki at moszumanska.debian.org
Fri Jun 30 09:03:49 UTC 2017


This is an automated email from the git hooks/post-receive script.

takaki pushed a commit to branch master
in repository python-kajiki.

commit f5f08d0b9cd5c383ae0c51136c7d95697e9e400d
Author: TANIGUCHI Takaki <takaki at asis.media-as.org>
Date:   Fri Jun 30 17:57:40 2017 +0900

    New upstream version 0.7.0
---
 CHANGES.rst                  |  6 +++++
 Kajiki.egg-info/PKG-INFO     | 10 ++++++--
 Kajiki.egg-info/requires.txt |  6 ++++-
 PKG-INFO                     | 10 ++++++--
 README.rst                   |  2 +-
 kajiki/i18n.py               | 12 +++++++---
 kajiki/template.py           |  2 +-
 kajiki/tests/test_xml.py     | 56 +++++++++++++++++++++++++++++++++++++++++---
 kajiki/version.py            |  2 +-
 kajiki/xml_template.py       | 43 ++++++++++++++++++++++++++++++++++
 setup.py                     | 11 +++++++++
 11 files changed, 146 insertions(+), 14 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 9150aec..14f42ca 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,12 @@
 CHANGES
 =======
 
+0.7.0 (2017-06-27)
+------------------
+
+* Text for i18n is now extracted ignoring the empty spaces surrounding the text itself. Empty text will always be treated as non translatable nodes for performance reasons.
+* ``extract_python`` option will now report syntax errors when extracting text for translation.
+
 0.6.3 (2017-05-25)
 ------------------
 
diff --git a/Kajiki.egg-info/PKG-INFO b/Kajiki.egg-info/PKG-INFO
index b6df910..255e661 100644
--- a/Kajiki.egg-info/PKG-INFO
+++ b/Kajiki.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Kajiki
-Version: 0.6.3
+Version: 0.7.0
 Summary: Fast XML-based template engine with Genshi syntax and Jinja blocks
 Home-page: https://github.com/nandoflorestan/kajiki
 Author: Nando Florestan
@@ -64,7 +64,7 @@ Description: Kajiki provides fast well-formed XML templates
         We use Travis_ for continuous integration.
         
         
-        .. _Documentation: http://pythonhosted.org/Kajiki/
+        .. _Documentation: http://kajiki.readthedocs.org/
         .. _license: https://github.com/nandoflorestan/kajiki/blob/master/LICENSE.rst
         .. _`issue tracker`: https://github.com/nandoflorestan/kajiki/issues
         .. _GitHub: https://github.com/nandoflorestan/kajiki
@@ -78,6 +78,12 @@ Description: Kajiki provides fast well-formed XML templates
         CHANGES
         =======
         
+        0.7.0 (2017-06-27)
+        ------------------
+        
+        * Text for i18n is now extracted ignoring the empty spaces surrounding the text itself. Empty text will always be treated as non translatable nodes for performance reasons.
+        * ``extract_python`` option will now report syntax errors when extracting text for translation.
+        
         0.6.3 (2017-05-25)
         ------------------
         
diff --git a/Kajiki.egg-info/requires.txt b/Kajiki.egg-info/requires.txt
index 211a828..c1cbf47 100644
--- a/Kajiki.egg-info/requires.txt
+++ b/Kajiki.egg-info/requires.txt
@@ -1 +1,5 @@
-nine
\ No newline at end of file
+nine
+
+[testing]
+babel
+nose
\ No newline at end of file
diff --git a/PKG-INFO b/PKG-INFO
index b6df910..255e661 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Kajiki
-Version: 0.6.3
+Version: 0.7.0
 Summary: Fast XML-based template engine with Genshi syntax and Jinja blocks
 Home-page: https://github.com/nandoflorestan/kajiki
 Author: Nando Florestan
@@ -64,7 +64,7 @@ Description: Kajiki provides fast well-formed XML templates
         We use Travis_ for continuous integration.
         
         
-        .. _Documentation: http://pythonhosted.org/Kajiki/
+        .. _Documentation: http://kajiki.readthedocs.org/
         .. _license: https://github.com/nandoflorestan/kajiki/blob/master/LICENSE.rst
         .. _`issue tracker`: https://github.com/nandoflorestan/kajiki/issues
         .. _GitHub: https://github.com/nandoflorestan/kajiki
@@ -78,6 +78,12 @@ Description: Kajiki provides fast well-formed XML templates
         CHANGES
         =======
         
+        0.7.0 (2017-06-27)
+        ------------------
+        
+        * Text for i18n is now extracted ignoring the empty spaces surrounding the text itself. Empty text will always be treated as non translatable nodes for performance reasons.
+        * ``extract_python`` option will now report syntax errors when extracting text for translation.
+        
         0.6.3 (2017-05-25)
         ------------------
         
diff --git a/README.rst b/README.rst
index cbb76b4..ede7a47 100644
--- a/README.rst
+++ b/README.rst
@@ -56,7 +56,7 @@ used SourceForge_ for the hg repository, issue tracker and forums.
 We use Travis_ for continuous integration.
 
 
-.. _Documentation: http://pythonhosted.org/Kajiki/
+.. _Documentation: http://kajiki.readthedocs.org/
 .. _license: https://github.com/nandoflorestan/kajiki/blob/master/LICENSE.rst
 .. _`issue tracker`: https://github.com/nandoflorestan/kajiki/issues
 .. _GitHub: https://github.com/nandoflorestan/kajiki
diff --git a/kajiki/i18n.py b/kajiki/i18n.py
index 0e6b1e1..61651f6 100644
--- a/kajiki/i18n.py
+++ b/kajiki/i18n.py
@@ -3,6 +3,8 @@
 from __future__ import (absolute_import, division, print_function,
                         unicode_literals)
 from io import BytesIO
+from tokenize import TokenError
+
 from .ir import TranslatableTextNode, ExprNode
 
 
@@ -12,6 +14,7 @@ def gettext(s):
 
 def extract(fileobj, keywords, comment_tags, options):
     """Babel entry point that extracts translation strings from XML templates."""
+    from .template import KajikiSyntaxError
     from .xml_template import _Parser, _Compiler, _DomTransformer
 
     try:
@@ -35,6 +38,9 @@ def extract(fileobj, keywords, comment_tags, options):
             if node.text.strip():
                 yield (node.lineno, '_', node.text, [])
         elif extract_expr and isinstance(node, ExprNode):
-            for e in extract_python(BytesIO(node.text.encode('utf-8')),
-                                    keywords, comment_tags, options):
-                yield (node.lineno, e[1], e[2], e[3])
\ No newline at end of file
+            try:
+                for e in extract_python(BytesIO(node.text.encode('utf-8')),
+                                        keywords, comment_tags, options):
+                    yield (node.lineno, e[1], e[2], e[3])
+            except (TokenError, SyntaxError) as e:
+                raise KajikiSyntaxError(e, source, '<string>', node.lineno, 0)
\ No newline at end of file
diff --git a/kajiki/template.py b/kajiki/template.py
index 2a46ce3..e6b9c2a 100644
--- a/kajiki/template.py
+++ b/kajiki/template.py
@@ -66,7 +66,7 @@ class _Template(object):
         base_globals = self.base_globals or {}
         self.__globals__ = dict(base_globals, local=self, self=self,
             defined=lambda x: x in self.__globals__,
-            literal=literal, Markup=literal,
+            literal=literal, Markup=literal, _=i18n.gettext,
             __builtins__=__builtins__, __kj__=kajiki)
         self.__globals__['value_of'] = self.__globals__.get
         for k, v in self.__methods__:
diff --git a/kajiki/tests/test_xml.py b/kajiki/tests/test_xml.py
index 9463f59..81353dc 100644
--- a/kajiki/tests/test_xml.py
+++ b/kajiki/tests/test_xml.py
@@ -826,9 +826,7 @@ class TestTranslation(TestCase):
         Hello
         World</p></xml>'''
         expected = {
-            False: '''<xml><div>TRANSLATED(Hi)</div><p>TRANSLATED(
-
-        Hello
+            False: '''<xml><div>TRANSLATED(Hi)</div><p>\n\n        TRANSLATED(Hello
         World)</p></xml>''',
             True: '''<xml><div>TRANSLATED(Hi)</div><p>TRANSLATED(Hello
         World)</p></xml>'''
@@ -850,6 +848,58 @@ class TestTranslation(TestCase):
             finally:
                 i18n.gettext = default_gettext
 
+    def test_extract_python_inside(self):
+        src = '''<xml><div>${_('hi')}</div><p>
+
+        Hello
+        World</p></xml>'''
+        expected = '''<xml><div>xi</div><p>\n\n        TRANSLATED(Hello
+        World)</p></xml>'''
+
+        # Build translation table
+        messages = {'hi': 'xi'}
+        for _, _, msgid, _ in i18n.extract(BytesIO(src.encode('utf-8')), [], None, {
+            'extract_python': True
+        }):
+            messages[msgid] = 'TRANSLATED(%s)' % msgid
+
+        # Provide a fake translation function
+        default_gettext = i18n.gettext
+        i18n.gettext = lambda s: messages[s]
+        try:
+            perform(src, expected)
+        finally:
+            i18n.gettext = default_gettext
+
+    def test_extract_python_inside_invalid(self):
+        src = '''<xml><div>${_('hi' +}</div></xml>'''
+        try:
+            x = list(i18n.extract(BytesIO(src.encode('utf-8')), [], None, {
+                'extract_python': True
+            }))
+        except KajikiSyntaxError as e:
+            assert "${_('hi' +" in str(e)
+        else:
+            assert False, 'Should have raised'
+
+
+class TestDOMTransformations(TestCase):
+    def test_empty_text_extraction(self):
+        doc = kajiki.xml_template._Parser('<string>', '''<span>  text  </span>''').parse()
+        doc = kajiki.xml_template._DomTransformer(doc, strip_text=False).transform()
+        text_data = [n.data for n in doc.firstChild.childNodes]
+        self.assertEqual(['  ', 'text', '  '], text_data)
+
+    def test_empty_text_extraction_lineno(self):
+        doc = kajiki.xml_template._Parser('<string>', '''<span>
+
+          text
+
+            </span>''').parse()
+        doc = kajiki.xml_template._DomTransformer(doc, strip_text=False).transform()
+        linenos = [n.lineno for n in doc.firstChild.childNodes]
+        self.assertEqual([1, 3, 3], linenos)  # Last node starts on same line as it starts with \n
+
 
 class TestErrorReporting(TestCase):
     def test_syntax_error(self):
diff --git a/kajiki/version.py b/kajiki/version.py
index 82b8273..58b5751 100644
--- a/kajiki/version.py
+++ b/kajiki/version.py
@@ -3,4 +3,4 @@ from __future__ import (absolute_import, division, print_function,
                         unicode_literals)
 
 __version__ = '0.6'
-__release__ = '0.6.3'
+__release__ = '0.7.0'
diff --git a/kajiki/xml_template.py b/kajiki/xml_template.py
index 27ba86d..9632015 100644
--- a/kajiki/xml_template.py
+++ b/kajiki/xml_template.py
@@ -703,6 +703,7 @@ class _DomTransformer(object):
 
         self.doc = self._expand_directives(self.doc)
         self.doc = self._merge_text_nodes(self.doc)
+        self.doc = self._extract_nodes_leading_and_trailing_spaces(self.doc)
         if self._strip_text:
             self.doc = self._strip_text_nodes(self.doc)
         return self.doc
@@ -744,6 +745,48 @@ class _DomTransformer(object):
         return tree
 
     @classmethod
+    def _extract_nodes_leading_and_trailing_spaces(cls, tree):
+        """Extract the leading and traling spaces of TextNodes to separate nodes.
+
+        This is explicitly intended to make i18n easier, as we don't want people having
+        to pay attention to spaces at being and end of text when translating it. So those
+        are always extracted and only the meaningful part is preserved for translation.
+        """
+        for child in tree.childNodes:
+            if isinstance(child, dom.Text):
+                if not getattr(child, '_cdata', False):
+                    if not child.data.strip():
+                        # Already a totally empty node, do nothing...
+                        continue
+
+                    lstripped_data = child.data.lstrip()
+                    if len(lstripped_data) != len(child.data):
+                        # There is text to strip at begin, create a new text node with empty space
+                        empty_text_len = len(child.data) - len(lstripped_data)
+                        empty_text = child.data[:empty_text_len]
+                        begin_node = child.ownerDocument.createTextNode(empty_text)
+                        begin_node.lineno = child.lineno
+                        begin_node.escaped = child.escaped
+                        tree.insertBefore(newChild=begin_node, refChild=child)
+                        child.lineno += child.data[:empty_text_len].count('\n')
+                        child.data = lstripped_data
+
+                    rstripped_data = child.data.rstrip()
+                    if len(rstripped_data) != len(child.data):
+                        # There is text to strip at end, create a new text node with empty space
+                        empty_text_len = len(child.data) - len(rstripped_data)
+                        empty_text = child.data[-empty_text_len:]
+                        end_node = child.ownerDocument.createTextNode(empty_text)
+                        end_node.lineno = child.lineno + child.data[:-empty_text_len].count('\n')
+                        end_node.escaped = child.escaped
+                        tree.replaceChild(newChild=end_node, oldChild=child)
+                        tree.insertBefore(newChild=child, refChild=end_node)
+                        child.data = rstripped_data
+            else:
+                cls._extract_nodes_leading_and_trailing_spaces(child)
+        return tree
+
+    @classmethod
     def _strip_text_nodes(cls, tree):
         """Strips empty characters in all text nodes."""
         for child in tree.childNodes:
diff --git a/setup.py b/setup.py
index 1c9f22d..becac66 100755
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,14 @@ def content_of(*files):
     return '\n'.join(content)
 
 
+import sys
+py_version = sys.version_info[:2]
+
+TEST_DEPENDENCIES = ['babel', 'nose']
+if py_version == (2, 6):
+    TEST_DEPENDENCIES.extend(['importlib'])
+
+
 setup(name='Kajiki',
       version=__release__,
       description='Fast XML-based template engine with Genshi syntax and '
@@ -59,6 +67,9 @@ setup(name='Kajiki',
       include_package_data=True,
       zip_safe=False,
       install_requires=['nine'],
+      extras_require = {
+        'testing': TEST_DEPENDENCIES,
+      },
       test_suite='kajiki.tests',
       entry_points="""
           [babel.extractors]

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-kajiki.git



More information about the Python-modules-commits mailing list