Make rst as_html handle errors a little more nicely.
[zzz-pokedex.git] / pokedex / db / rst.py
index 474a275..a77feef 100644 (file)
@@ -33,6 +33,8 @@ are, apparently, global.
     return a reST node.
 """
 
+import cgi
+
 from docutils.frontend import OptionParser
 from docutils.io import Output
 import docutils.nodes
@@ -40,6 +42,8 @@ from docutils.parsers.rst import Parser, roles
 import docutils.utils
 from docutils.writers.html4css1 import Writer as HTMLWriter
 
+import sqlalchemy.types
+
 ### Subclasses of bits of docutils, to munge it into doing what I want
 class HTMLFragmentWriter(HTMLWriter):
     """Translates reST to HTML, but only as a fragment.  Enclosing <body>,
@@ -85,7 +89,7 @@ roles.register_local_role('data', data_role)
 
 class RstString(object):
     """Wraps a reStructuredText string.  Stringifies to the original text, but
-    may be translated to HTML with .to_html().
+    may be translated to HTML with .as_html().
     """
 
     def __init__(self, source_text, document_properties={}):
@@ -129,8 +133,17 @@ class RstString(object):
         """Returns the string as HTML4."""
 
         document = self.rest_document
-        destination = UnicodeOutput()
 
+        # Check for errors; don't want to leave the default error message cruft
+        # in here
+        if document.next_node(condition=docutils.nodes.system_message):
+            # Boo!  Cruft.
+            return u"""
+                <p><em>Error in markup!  Raw source is below.</em></p>
+                <pre>{0}</pre>
+            """.format( cgi.escape(self.source_text) )
+
+        destination = UnicodeOutput()
         writer = HTMLFragmentWriter()
         return writer.write(document, destination)
 
@@ -138,7 +151,7 @@ class RstString(object):
 class MoveEffectProperty(object):
     """Property that wraps a move effect.  Used like this:
 
-        MoveClass.effect = MoveEffectProperty()
+        MoveClass.effect = MoveEffectProperty('effect')
 
         some_move.effect            # returns an RstString
         some_move.effect.as_html    # returns a chunk of HTML
@@ -162,3 +175,17 @@ class MoveEffectProperty(object):
         return RstString(getattr(move.move_effect, self.effect_column),
                          document_properties=dict(
                              _pokedex_handle_data=data_role_func))
+
+class RstTextColumn(sqlalchemy.types.TypeDecorator):
+    """Generic column type for reST text.
+
+    Do NOT use this for move effects!  They need to know what move they belong
+    to so they can fill in, e.g., effect chances.
+    """
+    impl = sqlalchemy.types.Unicode
+
+    def process_bind_param(self, value, dialect):
+        return unicode(value)
+
+    def process_result_value(self, value, dialect):
+        return RstString(value)