[cpif] r425 - branches/alvaro/frontend-web

svn at argo.es svn at argo.es
Thu Oct 25 01:09:46 CEST 2007


Author: alvaro
Date: Thu Oct 25 01:09:45 2007
New Revision: 425

Log:
Primeros pasos...


Modified:
   branches/alvaro/frontend-web/parser_bbcode.py

Modified: branches/alvaro/frontend-web/parser_bbcode.py
==============================================================================
--- branches/alvaro/frontend-web/parser_bbcode.py	(original)
+++ branches/alvaro/frontend-web/parser_bbcode.py	Thu Oct 25 01:09:45 2007
@@ -1,6 +1,10 @@
 # $Id$
-"""BBCode to HTML parser"""
 
+# TODO: Argumentos en los quotes y en los urls
+# TODO: Url selfargumentada
+# TODO: Integrar unittest
+
+import re
 
 # Allow BBCode syntax errors?
 allow_errors = False
@@ -19,256 +23,159 @@
     "img": ('<img src="%(arg)s" />', None, True, None)
 }
 
-def escape(text):
-  """Escape the conflictive characters into its entities. Please note that
-he "&" character must be traslated into "&amp;" in the URLS, as said
-in http://www.htmlhelp.com/tools/validator/problems.html#amp"""
-
-  entities = {
-      '"': '&quot;', 
-      "'": "&apos;"
-      }
-# Si hay que hacer otras sustituciones este codigo puede ser util
-#  import re
-#  pat = "(%s)" % "|".join( map(re.escape, entities.keys())  )
-#  return re.sub( pat, lambda m:entities[m.group()], text )
-  import xml.sax.saxutils
-  return xml.sax.saxutils.escape(text, entities)
-
-
-class BBCodeParser:
-  """A BBCode to HTML parser"""
-
-  _open = "["
-  _close = "]"
-  _regexp_start = "\%s.*?\%s" % (_open, _close)
-  _regexp_end = "\%s(.*?)\%s" % (_open, _close)
-
-  def __init__(self, context = None):
-    self._context = context
-    self._status = ""
-    self._text = ""
-    self._tokens = []
-    self._tags = []
-    self._parsed = []
-  def _reset(self):
-    """Resets the internal arrays."""
-    self._status = ""
-    self._tokens = []
-    self._tags = []
-    self._parsed = []
-
-  def feed(self, text):
-    """Sets the text to parse"""
-    self._text = text
-    self._reset()
-    self._tokenize()
-    self._status =  self._parse()
-
-  def get_text(self):
-    return self._status, "".join([text for text, dummy in self._parsed])
-
-  def get_tokens(self):
-    return self._status, self._parsed
-
-  def _tokenize(self):
-    """Tokenize the string and the tags in two separates lists
-    Should be called after before _parse."""
-    import re
-    self._tokens = re.split(self._regexp_start, self._text)
-    self._tags = re.findall(self._regexp_end, self._text)
-
-  def _close_tag_to_html(self, tag):
-    """Translate the BBCode tag to HTML anc close it."""
-    return allowed_tags[tag][1] or ""
-
-  def _tag_to_html(self, tag):
-    """Translates the BBCode tag to HTML"""
-    aux = allowed_tags[tag[0]]
-    if not tag[1]:
-      aux = allowed_tags.get(tag[0] + "*", aux) # Permitimos tag* que no lleva argumentos y puede ser distinto
-    if tag[1]:
-      tag[1] = tag[1].strip('"')
-      tag[1] = tag[1].strip("'")
-    return aux[0] % {"arg": escape(tag[1]) if tag[1] else '' }
-
-  def _tag_closes(self, tag):
-    """Returns true if the tags needs to be closed"""
-    if tag[0].startswith("/"):
-      return allowed_tags[tag[0][1:]][1]
-    return allowed_tags[tag[0]][1]
-
-  def _tag_needs_args(self, tag):
-    """Returns true if the tag needs arguments"""
-    if allowed_tags.get(tag + "*", False):
-      return False
-    return allowed_tags[tag][2]
-  
-  def _parse(self):
-    """Do the parsing.
-    Should be called after _reset, and _tokenize."""
-    def get_context():
-      return allowed_tags.get(stack[-1], None)[3] if stack else self._context
-    def check_context(tag):
-      if allowed_tags[tag][3] == self._context and self._context:
-        return False
-      else:
-        return True
-    stack = []
-    self._parsed.append((True, self._tokens.pop(0), get_context()))
-    while self._tags:
-      tag = self._tags.pop(0)
-      tag = tag.split("=", 1)
-      tag[0] = tag[0].strip()
-      if tag[0].startswith("/") and tag[0][1:] in allowed_tags.keys() and stack:
-        if tag[0][1:] == stack[-1]:
-          self._parsed.append((False, self._close_tag_to_html(stack[-1]), get_context()))
-          stack.pop(-1)
-        elif not allow_errors: 
-          return "Error, tratando de cerrar %s%s%s no abierto antes" % (self._open, tag[0], self._close)
-        else: # Si alguien activa allow_errors mereceria la mas lenta y dolorosa muerte
-              # Esto es una chapuza para usuarios estupidos y chapuceros (y ni se si funciona)
-          self._parsed.append((False, "%s%s%s" % (self._open, tag[0], self._close), tag[0]))
-        if self._tokens and self._tag_closes(tag):
-          self._parsed.append((True, self._tokens.pop(0), get_context()))
-
-      elif tag[0] in allowed_tags.keys():
-        if not check_context(tag[0]):
-          return "Error, anidado no valido"
-        tag.append(None)
-        stack.append(tag[0])
-        if self._tag_needs_args(tag[0]) and tag[1] == None: 
-          tag[1] = self._tokens[0]
-          if not allow_errors and not tag[1]:
-            return "Error, no se ha pasado el argumento a %s%s%s" % (self._open, tag[0], self._close)
-        self._parsed.append((False, self._tag_to_html(tag), get_context()))
-        if not self._tag_closes(tag) and self._tokens:
-          self._tokens.pop(0)
-        if self._tokens: 
-          self._parsed.append((True, self._tokens.pop(0), get_context()))
-
-      else: # Si no conozco el tag se lo paso tal cual
-        self._parsed.append((True, "%s%s%s" % (self._open, tag[0], self._close), get_context()))
-        if self._tokens:
-          self._parsed.append((True, self._tokens.pop(0), get_context()))
-    
-    if stack and allow_errors:
-      while stack: # No me responsabilizo de lo que salga aqui...
-        self._parsed.append((False, self._close_tag_to_html(stack[-1]), close_tag))
-        stack.pop(-1)
-    elif stack:
-      return "Error, falta cerrar el tag %s%s%s" % (self._open, stack[-1], self._close)
-    return False
-
-def parse(text, context = None):
-  """Parses the text into BBCode. It returns the exit code and a list of tuples
-in the form [(Boolean,"text")]. The first element tells whether "text" was
-untouched or analysed."""
-  parser = BBCodeParser(context = context)
-  parser.feed(text)
-  return parser.get_tokens()
-
-import unittest
-class TestBBCode(unittest.TestCase):
-  """Test Case for the BBCode parser"""
-  correct_bbcode = (
-      ('[ b]hola[/b]', '<strong>hola</strong>'), 
-      ('[b ]hola[/b]', '<strong>hola</strong>'), 
-      ('[ b ]hola[/b]', '<strong>hola</strong>'), 
-
-      ('[b]hola[ /b]', '<strong>hola</strong>'), 
-      ('[b]hola[/b ]', '<strong>hola</strong>'), 
-      ('[b]hola[ /b ]', '<strong>hola</strong>'), 
-
-
-      ('[b]hola[/b]', '<strong>hola</strong>'), 
-      ('antes [b]hola[/b]', 'antes <strong>hola</strong>'), 
-      ('[b]hola[/b] despues', '<strong>hola</strong> despues'), 
-      ('antes [b]hola[/b] despues', 'antes <strong>hola</strong> despues'), 
-
-      ('[url]la direccion[/url]', '<a href="la direccion">la direccion</a>'), 
-      ('antes [url]la direccion[/url]', 'antes <a href="la direccion">la direccion</a>'), 
-      ('[url]la direccion[/url] despues', '<a href="la direccion">la direccion</a> despues'), 
-      ('antes [url]la direccion[/url] despues', 'antes <a href="la direccion">la direccion</a> despues'), 
-
-      ('[url="la direccion"]el texto[/url]', '<a href="la direccion">el texto</a>'), 
-      ('antes [url="la direccion"]el texto[/url]', 'antes <a href="la direccion">el texto</a>'), 
-      ('[url="la direccion"]el texto[/url] despues', '<a href="la direccion">el texto</a> despues'), 
-      ('antes [url="la direccion"]el texto[/url] despues', 'antes <a href="la direccion">el texto</a> despues'), 
-
-      ('[url="la direccion"]el texto[/url]', '<a href="la direccion">el texto</a>'), 
-      
-      ('[url="http://example.org/uno&dos"]el texto[/url]', '<a href="http://example.org/uno&amp;dos">el texto</a>'), 
-
-      ('[url=la direccion]el texto[/url]', '<a href="la direccion">el texto</a>'), 
-      ('antes [url=la direccion]el texto[/url]', 'antes <a href="la direccion">el texto</a>'), 
-      ('[url =la direccion]el texto[/url] despues', '<a href="la direccion">el texto</a> despues'), 
-      ('antes [url=la direccion]el texto[/url] despues', 'antes <a href="la direccion">el texto</a> despues'), 
-
-      ('[quote=paco]Hola[/quote]', '<blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote>'), 
-      ('antes [quote=paco]Hola[/quote]', 'antes <blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote>'), 
-      ('[quote=paco]Hola[/quote] despues', '<blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote> despues'), 
-      ('antes [quote=paco]Hola[/quote] despues', 'antes <blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote> despues'), 
-
-      ('[quote]Hola[/quote]', '<blockquote>Hola</blockquote>'), 
-      ('antes [quote]Hola[/quote]', 'antes <blockquote>Hola</blockquote>'), 
-      ('[quote]Hola[/quote] despues', '<blockquote>Hola</blockquote> despues'), 
-      ('antes [quote]Hola[/quote] despues', 'antes <blockquote>Hola</blockquote> despues'), 
-  
-      ('[u]hola[/u]', '<span style="text-decoration:underline">hola</span>'), 
-      
-      ('[size=20px]hola[/size]', '<span style="font-size:20px">hola</span>'), 
-
-      ('[n]hola[/n]', '[n]hola[/n]'), 
-
-      ("[img]laimagen1[/img]", '<img src="laimagen1" />'), 
-      ("antes [img]laimagen2[/img]", 'antes <img src="laimagen2" />'), 
-      ("[img]laimagen3[/img] despues", '<img src="laimagen3" /> despues'), 
-      ("antes [img]laimagen4[/img] despues", 'antes <img src="laimagen4" /> despues')
-  )
-
-  incorrect_bbcode = (
-      '[i]bla bla bla [b]hola[/n][/i]', 
-      '[b]Ay[/ b ]', 
-      '[b]Ay[ / b ]', 
-      '[b]Ay[/]', 
-      '[b]Ay, se me ha olvidado cerrar', 
-      '[url][/url]', 
-      '[b][/url]hola[/url]', 
-      '[b]foo[url]hola[/b][/url]', 
-      """Un texto [b]mas[/b] largo, con [b]negritas y [n]cursivas[/i]
-       [/b] e incluso [url="laurl"]enlaces [/b]con negritas[/b] dentro[/url]""")
-
-  xss = (
-      """[url="hola'"]adios[/url]""", 
-      """[url="hola''"'"'"]adios[/url]""", 
-)
-
-
-  def testCorrectBBCode(self):
-    """Test if the translation goes well."""
-    bbcode_list = []
-    html_list = []
-    global allow_errors
-    allow_errors = False
-    for bbcode, html in self.correct_bbcode:
-      bbcode_list.append(bbcode)
-      html_list.append(html)
-      retval, result = parse(bbcode)
-      assert not retval
-      self.assertEqual(html, "".join(text for dummy, text, dummy in result))
-    retval, result = parse("".join(bbcode_list))
-    assert not retval
-    self.assertEqual("".join(html_list), "".join(text for dummy, text, dummy in result))
-  
-  def testIncorrectBBCode(self):
-    """Test if the translation fails using bad formed BBCode."""
-    global allow_errors
-    allow_errors = False
-    for bbcode in self.incorrect_bbcode:
-      retval, result = parse(bbcode)
-      assert retval
+tags = {
+        'b': ['b','b'],
+        'size': ['size', 'size'],
+        'quote': ['quote(?:="([^"]+)")?','quote'],
+        'url': ['url', 'url'],
+        'img': ['img', None],
+    }
 
-if __name__ == "__main__":
-  unittest.main()
+regexp_tag = re.compile("(\[.*?\])")
+
+for key, value in tags.iteritems():
+    tags[key] = [ re.compile("\[%s\]" % value[0]), re.compile("\[/%s\]"% value[1]) if value[1] else None ]
 
+
+def escape(text):
+    entities = {
+            '"': '&quot;', 
+            "'": "&apos;"
+    }
+    # Si hay que hacer otras sustituciones este codigo puede ser util
+#    import re
+#    pat = "(%s)" % "|".join( map(re.escape, entities.keys())  )
+#    return re.sub( pat, lambda m:entities[m.group()], text )
+    import xml.sax.saxutils
+    return xml.sax.saxutils.escape(text, entities)
+
+
+def parse(text):
+    print "Parseo--->\n %s" % text
+    before = []
+    control = True
+    while control:
+        ret = regexp_tag.split(text,1)
+        before.append(ret[0])
+        tag = ret[1]
+        after = ret[2]
+        for key,value in tags.iteritems():
+            if value[0].match(tag):
+                tag = ('BBCODE',True,tag,None,False)
+                control = False
+                break
+            elif value[1] and value[1].match(tag):
+                tag = ('BBCODE',False,tag,None,False)
+                control = False
+                break
+        if control:
+            before.append(tag)
+            text = after
+    print "".join(before), tag, after
+    return "".join(before), tag, after
+
+#import unittest
+#class TestBBCode(unittest.TestCase):
+#  """Test Case for the BBCode parser"""
+#  correct_bbcode = (
+#      ('[ b]hola[/b]', '<strong>hola</strong>'), 
+#      ('[b ]hola[/b]', '<strong>hola</strong>'), 
+#      ('[ b ]hola[/b]', '<strong>hola</strong>'), 
+#
+#      ('[b]hola[ /b]', '<strong>hola</strong>'), 
+#      ('[b]hola[/b ]', '<strong>hola</strong>'), 
+#      ('[b]hola[ /b ]', '<strong>hola</strong>'), 
+#
+#
+#      ('[b]hola[/b]', '<strong>hola</strong>'), 
+#      ('antes [b]hola[/b]', 'antes <strong>hola</strong>'), 
+#      ('[b]hola[/b] despues', '<strong>hola</strong> despues'), 
+#      ('antes [b]hola[/b] despues', 'antes <strong>hola</strong> despues'), 
+#
+#      ('[url]la direccion[/url]', '<a href="la direccion">la direccion</a>'), 
+#      ('antes [url]la direccion[/url]', 'antes <a href="la direccion">la direccion</a>'), 
+#      ('[url]la direccion[/url] despues', '<a href="la direccion">la direccion</a> despues'), 
+#      ('antes [url]la direccion[/url] despues', 'antes <a href="la direccion">la direccion</a> despues'), 
+#
+#      ('[url="la direccion"]el texto[/url]', '<a href="la direccion">el texto</a>'), 
+#      ('antes [url="la direccion"]el texto[/url]', 'antes <a href="la direccion">el texto</a>'), 
+#      ('[url="la direccion"]el texto[/url] despues', '<a href="la direccion">el texto</a> despues'), 
+#      ('antes [url="la direccion"]el texto[/url] despues', 'antes <a href="la direccion">el texto</a> despues'), 
+#
+#      ('[url="la direccion"]el texto[/url]', '<a href="la direccion">el texto</a>'), 
+#      
+#      ('[url="http://example.org/uno&dos"]el texto[/url]', '<a href="http://example.org/uno&amp;dos">el texto</a>'), 
+#
+#      ('[url=la direccion]el texto[/url]', '<a href="la direccion">el texto</a>'), 
+#      ('antes [url=la direccion]el texto[/url]', 'antes <a href="la direccion">el texto</a>'), 
+#      ('[url =la direccion]el texto[/url] despues', '<a href="la direccion">el texto</a> despues'), 
+#      ('antes [url=la direccion]el texto[/url] despues', 'antes <a href="la direccion">el texto</a> despues'), 
+#
+#      ('[quote=paco]Hola[/quote]', '<blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote>'), 
+#      ('antes [quote=paco]Hola[/quote]', 'antes <blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote>'), 
+#      ('[quote=paco]Hola[/quote] despues', '<blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote> despues'), 
+#      ('antes [quote=paco]Hola[/quote] despues', 'antes <blockquote><h4>paco escribi&oacute;:</h4>Hola</blockquote> despues'), 
+#
+#      ('[quote]Hola[/quote]', '<blockquote>Hola</blockquote>'), 
+#      ('antes [quote]Hola[/quote]', 'antes <blockquote>Hola</blockquote>'), 
+#      ('[quote]Hola[/quote] despues', '<blockquote>Hola</blockquote> despues'), 
+#      ('antes [quote]Hola[/quote] despues', 'antes <blockquote>Hola</blockquote> despues'), 
+#  
+#      ('[u]hola[/u]', '<span style="text-decoration:underline">hola</span>'), 
+#      
+#      ('[size=20px]hola[/size]', '<span style="font-size:20px">hola</span>'), 
+#
+#      ('[n]hola[/n]', '[n]hola[/n]'), 
+#
+#      ("[img]laimagen1[/img]", '<img src="laimagen1" />'), 
+#      ("antes [img]laimagen2[/img]", 'antes <img src="laimagen2" />'), 
+#      ("[img]laimagen3[/img] despues", '<img src="laimagen3" /> despues'), 
+#      ("antes [img]laimagen4[/img] despues", 'antes <img src="laimagen4" /> despues')
+#  )
+#
+#  incorrect_bbcode = (
+#      '[i]bla bla bla [b]hola[/n][/i]', 
+#      '[b]Ay[/ b ]', 
+#      '[b]Ay[ / b ]', 
+#      '[b]Ay[/]', 
+#      '[b]Ay, se me ha olvidado cerrar', 
+#      '[url][/url]', 
+#      '[b][/url]hola[/url]', 
+#      '[b]foo[url]hola[/b][/url]', 
+#      """Un texto [b]mas[/b] largo, con [b]negritas y [n]cursivas[/i]
+#       [/b] e incluso [url="laurl"]enlaces [/b]con negritas[/b] dentro[/url]""")
+#
+#  xss = (
+#      """[url="hola'"]adios[/url]""", 
+#      """[url="hola''"'"'"]adios[/url]""", 
+#)
+#
+#
+#  def testCorrectBBCode(self):
+#    """Test if the translation goes well."""
+#    bbcode_list = []
+#    html_list = []
+#    global allow_errors
+#    allow_errors = False
+#    for bbcode, html in self.correct_bbcode:
+#      bbcode_list.append(bbcode)
+#      html_list.append(html)
+#      retval, result = parse(bbcode)
+#      assert not retval
+#      self.assertEqual(html, "".join(text for dummy, text, dummy in result))
+#    retval, result = parse("".join(bbcode_list))
+#    assert not retval
+#    self.assertEqual("".join(html_list), "".join(text for dummy, text, dummy in result))
+#  
+#  def testIncorrectBBCode(self):
+#    """Test if the translation fails using bad formed BBCode."""
+#    global allow_errors
+#    allow_errors = False
+#    for bbcode in self.incorrect_bbcode:
+#      retval, result = parse(bbcode)
+#      assert retval
+#
+if __name__ == "__main__":
+    parse("caca [f] adf [b] asgsdag [/b]")
+#  unittest.main()
+#



More information about the cpif mailing list