- functions - publicize text transforming functions
authorMarcin Koziej <mkoziej@ksi.(none)>
Mon, 28 Jan 2013 11:22:42 +0000 (12:22 +0100)
committerMarcin Koziej <mkoziej@ksi.(none)>
Mon, 28 Jan 2013 11:22:42 +0000 (12:22 +0100)
- small formatting fixes for html generation

librarian/functions.py
librarian/pyhtml.py
librarian/xmlutils.py

index 523b3d5..e91d7e1 100644 (file)
@@ -14,42 +14,47 @@ def _register_function(f):
     ns[f.__name__] = f
 
 
     ns[f.__name__] = f
 
 
-def reg_substitute_entities():
-    ENTITY_SUBSTITUTIONS = [
-        (u'---', u'—'),
-        (u'--', u'–'),
-        (u'...', u'…'),
-        (u',,', u'„'),
-        (u'"', u'”'),
-    ]
-
-    def substitute_entities(context, text):
-        """XPath extension function converting all entites in passed text."""
-        if isinstance(text, list):
-            text = ''.join(text)
-        for entity, substitutution in ENTITY_SUBSTITUTIONS:
-            text = text.replace(entity, substitutution)
-        return text
+ENTITY_SUBSTITUTIONS = [
+       (u'---', u'—'),
+       (u'--', u'–'),
+       (u'...', u'…'),
+       (u',,', u'„'),
+       (u'"', u'”'),
+]
+
+def substitute_entities(context, text):
+    """XPath extension function converting all entites in passed text."""
+    if isinstance(text, list):
+        text = ''.join(text)
+    for entity, substitutution in ENTITY_SUBSTITUTIONS:
+        text = text.replace(entity, substitutution)
+    return text
 
 
+
+def reg_substitute_entities():
     _register_function(substitute_entities)
 
 
     _register_function(substitute_entities)
 
 
+def strip(context, text):
+    """Remove unneeded whitespace from beginning and end"""
+    if isinstance(text, list):
+        text = ''.join(text)
+    return re.sub(r'\s+', ' ', text).strip()
+
+
 def reg_strip():
 def reg_strip():
-    def strip(context, text):
-        """Remove unneeded whitespace from beginning and end"""
-        if isinstance(text, list):
-            text = ''.join(text)
-        return re.sub(r'\s+', ' ', text).strip()
     _register_function(strip)
 
 
     _register_function(strip)
 
 
+def starts_white(context, text):
+    if isinstance(text, list):
+        text = ''.join(text)
+    if not text:
+        return False
+    return text[0].isspace()
+
+
 def reg_starts_white():
 def reg_starts_white():
-    def starts_white(context, text):
-        if isinstance(text, list):
-            text = ''.join(text)
-        if not text:
-            return False
-        return text[0].isspace()
     _register_function(starts_white)
 
 
     _register_function(starts_white)
 
 
@@ -63,44 +68,50 @@ def reg_ends_white():
     _register_function(ends_white)
 
 
     _register_function(ends_white)
 
 
+def wrap_words(context, text, wrapping):
+    """XPath extension function automatically wrapping words in passed text"""
+    if isinstance(text, list):
+        text = ''.join(text)
+    if not wrapping:
+        return text
+
+    words = re.split(r'\s', text)
+
+    line_length = 0
+    lines = [[]]
+    for word in words:
+        line_length += len(word) + 1
+        if line_length > wrapping:
+            # Max line length was exceeded. We create new line
+            lines.append([])
+            line_length = len(word)
+        lines[-1].append(word)
+    return '\n'.join(' '.join(line) for line in lines)
+
+
 def reg_wrap_words():
 def reg_wrap_words():
-    def wrap_words(context, text, wrapping):
-        """XPath extension function automatically wrapping words in passed text"""
-        if isinstance(text, list):
-            text = ''.join(text)
-        if not wrapping:
-            return text
-
-        words = re.split(r'\s', text)
-
-        line_length = 0
-        lines = [[]]
-        for word in words:
-            line_length += len(word) + 1
-            if line_length > wrapping:
-                # Max line length was exceeded. We create new line
-                lines.append([])
-                line_length = len(word)
-            lines[-1].append(word)
-        return '\n'.join(' '.join(line) for line in lines)
     _register_function(wrap_words)
 
 
     _register_function(wrap_words)
 
 
+def person_name(context, text):
+    """ Converts "Name, Forename" to "Forename Name" """
+    if isinstance(text, list):
+        text = ''.join(text)
+    return Person.from_text(text).readable()
+
+
 def reg_person_name():
 def reg_person_name():
-    def person_name(context, text):
-        """ Converts "Name, Forename" to "Forename Name" """
-        if isinstance(text, list):
-            text = ''.join(text)
-        return Person.from_text(text).readable()
     _register_function(person_name)
 
 
     _register_function(person_name)
 
 
+def texcommand(context, text):
+    """Remove non-letters"""
+    if isinstance(text, list):
+        text = ''.join(text)
+    return re.sub(r'[^a-zA-Z]', '', text).strip()
+
+
 def reg_texcommand():
 def reg_texcommand():
-    def texcommand(context, text):
-        """Remove non-letters"""
-        if isinstance(text, list):
-            text = ''.join(text)
-        return re.sub(r'[^a-zA-Z]', '', text).strip()
     _register_function(texcommand)
 
 
     _register_function(texcommand)
 
 
index a46659c..6df3647 100644 (file)
@@ -6,25 +6,27 @@
 from lxml import etree
 from librarian import OutputFile, RDFNS, DCNS
 from xmlutils import Xmill, tag, tagged, ifoption
 from lxml import etree
 from librarian import OutputFile, RDFNS, DCNS
 from xmlutils import Xmill, tag, tagged, ifoption
+from librarian import functions
 import re
 import random
 
 import re
 import random
 
+
 class EduModule(Xmill):
     def __init__(self, *args):
         super(EduModule, self).__init__(*args)
         self.activity_counter = 0
 class EduModule(Xmill):
     def __init__(self, *args):
         super(EduModule, self).__init__(*args)
         self.activity_counter = 0
+        self.register_text_filter(lambda t: functions.substitute_entities(None, t))
 
     def handle_powiesc(self, element):
         return u"""
 <div class="module" id="book-text">
 
     def handle_powiesc(self, element):
         return u"""
 <div class="module" id="book-text">
- <span class="teacher-toggle">
+<!-- <span class="teacher-toggle">
   <input type="checkbox" name="teacher-toggle" id="teacher-toggle"/>
   <label for="teacher-toggle">Pokaż treść dla nauczyciela</label>
   <input type="checkbox" name="teacher-toggle" id="teacher-toggle"/>
   <label for="teacher-toggle">Pokaż treść dla nauczyciela</label>
- </span>
+ </span>-->
 
 """, u"</div>"
 
 
 """, u"</div>"
 
-
     handle_autor_utworu = tag("span", "author")
     handle_nazwa_utworu = tag("h1", "title")
     handle_dzielo_nadrzedne = tag("span", "collection")
     handle_autor_utworu = tag("span", "author")
     handle_nazwa_utworu = tag("h1", "title")
     handle_dzielo_nadrzedne = tag("span", "collection")
@@ -183,18 +185,21 @@ class Excercise(EduModule):
             add_class += ' handles handles-%s' % handles
             self.options = {'handles': handles}
 
             add_class += ' handles handles-%s' % handles
             self.options = {'handles': handles}
 
-
         return '<div class="question%s" data-no="%d" %s>' %\
             (add_class, self.question_counter, solution_s), \
         return '<div class="question%s" data-no="%d" %s>' %\
             (add_class, self.question_counter, solution_s), \
-    "</div>"
+            "</div>"
 
 
 class Wybor(Excercise):
 
 
 class Wybor(Excercise):
-    def handle_pytanie(self, element):
-        pre, post = super(Wybor, self).handle_pytanie(element)
-        solutions = re.split(r"[, ]+", element.attrib['rozw'])
-        if len(solutions) == 1:
-            self.options = { 'single': True }
+    def handle_cwiczenie(self, element):
+        pre, post = super(Wybor, self).handle_cwiczenie(element)
+        is_single_choice = True
+        for p in element.xpath(".//pytanie"):
+            solutions = re.split(r"[, ]+", p.attrib['rozw'])
+            if len(solutions) != 1:
+                is_single_choice = False
+                break
+        self.options = {'single': is_single_choice}
         return pre, post
 
     def handle_punkt(self, element):
         return pre, post
 
     def handle_punkt(self, element):
@@ -221,7 +226,6 @@ class Wybor(Excercise):
             return super(Wybor, self).handle_punkt(element)
 
 
             return super(Wybor, self).handle_punkt(element)
 
 
-
 class Uporzadkuj(Excercise):
     def handle_pytanie(self, element):
         """
 class Uporzadkuj(Excercise):
     def handle_pytanie(self, element):
         """
index a3f9df9..d762320 100644 (file)
@@ -8,14 +8,25 @@ from collections import defaultdict
 
 
 class Xmill(object):
 
 
 class Xmill(object):
-    """Transforms XML to some text. 
+    """Transforms XML to some text.
     Used instead of XSLT which is difficult and cumbersome.
     Used instead of XSLT which is difficult and cumbersome.
-    
+
     """
     def __init__(self, options=None):
         self._options = []
         if options:
             self._options.append(options)
     """
     def __init__(self, options=None):
         self._options = []
         if options:
             self._options.append(options)
+        self.text_filters = []
+
+    def register_text_filter(self, fun):
+        self.text_filters.append(fun)
+
+    def filter_text(self, text):
+        for flt in self.text_filters:
+            if text is None:
+                return None
+            text = flt(text)
+        return text
 
     def generate(self, document):
         """Generate text from node using handlers defined in class."""
 
     def generate(self, document):
         """Generate text from node using handlers defined in class."""
@@ -26,7 +37,7 @@ class Xmill(object):
     def options(self):
         """Returnes merged scoped options for current node.
         """
     def options(self):
         """Returnes merged scoped options for current node.
         """
-        # Here we can see how a decision not to return the modified map 
+        # Here we can see how a decision not to return the modified map
         # leads to a need for a hack.
         return reduce(lambda a, b: a.update(b) or a, self._options, defaultdict(lambda: False))
 
         # leads to a need for a hack.
         return reduce(lambda a, b: a.update(b) or a, self._options, defaultdict(lambda: False))
 
@@ -54,8 +65,8 @@ class Xmill(object):
                 except ValueError:
                     pass
             if not ns:
                 except ValueError:
                     pass
             if not ns:
-                raise ValueError("Strange ns for tag: %s, nsmap: %s" % 
-                                 (element.tag, element.nsmap)) 
+                raise ValueError("Strange ns for tag: %s, nsmap: %s" %
+                                 (element.tag, element.nsmap))
         else:
             tagname = element.tag
 
         else:
             tagname = element.tag
 
@@ -63,7 +74,7 @@ class Xmill(object):
             meth_name = "handle_%s__%s" % (ns, tagname)
         else:
             meth_name = "handle_%s" % (tagname,)
             meth_name = "handle_%s__%s" % (ns, tagname)
         else:
             meth_name = "handle_%s" % (tagname,)
-        
+
         handler = getattr(self, meth_name, None)
         return handler
 
         handler = getattr(self, meth_name, None)
         return handler
 
@@ -84,7 +95,7 @@ class Xmill(object):
             options_scopes = len(self._options)
 
             if handler is None:
             options_scopes = len(self._options)
 
             if handler is None:
-                pre = [element.text]
+                pre = [self.filter_text(element.text)]
                 post = []
             else:
                 vals = handler(element)
                 post = []
             else:
                 vals = handler(element)
@@ -94,10 +105,10 @@ class Xmill(object):
                     return []
                 else:
                     if not isinstance(vals, tuple):
                     return []
                 else:
                     if not isinstance(vals, tuple):
-                        return [vals, element.tail]
+                        return [vals, self.filter_text(element.tail)]
                     else:
                     else:
-                        pre = [vals[0], element.text]
-                        post = [vals[1], element.tail]
+                        pre = [vals[0], self.filter_text(element.text)]
+                        post = [vals[1], self.filter_text(element.tail)]
 
             out = pre + [self._handle_element(child) for child in element] + post
         finally:
 
             out = pre + [self._handle_element(child) for child in element] + post
         finally: