Hello community,

here is the log from the commit of package python-CommonMark for 
openSUSE:Factory checked in at 2017-10-31 15:43:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-CommonMark (Old)
 and      /work/SRC/openSUSE:Factory/.python-CommonMark.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-CommonMark"

Tue Oct 31 15:43:45 2017 rev:4 rq:537519 version:0.7.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-CommonMark/python-CommonMark.changes      
2017-06-24 08:35:02.267438470 +0200
+++ /work/SRC/openSUSE:Factory/.python-CommonMark.new/python-CommonMark.changes 
2017-10-31 15:43:46.122277185 +0100
@@ -1,0 +2,6 @@
+Mon Oct 30 01:51:43 UTC 2017 - [email protected]
+
+- update to version 0.7.4:
+  * The CommonMark spec has been updated to 0.28.
+
+-------------------------------------------------------------------

Old:
----
  CommonMark-0.7.3.tar.gz

New:
----
  CommonMark-0.7.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-CommonMark.spec ++++++
--- /var/tmp/diff_new_pack.PVmQys/_old  2017-10-31 15:43:46.654257901 +0100
+++ /var/tmp/diff_new_pack.PVmQys/_new  2017-10-31 15:43:46.654257901 +0100
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define oldpython python
 Name:           python-CommonMark
-Version:        0.7.3
+Version:        0.7.4
 Release:        0
 Summary:        Python parser for the CommonMark Markdown spec
 License:        BSD-3-Clause

++++++ CommonMark-0.7.3.tar.gz -> CommonMark-0.7.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/.gitignore 
new/CommonMark-0.7.4/.gitignore
--- old/CommonMark-0.7.3/.gitignore     2016-04-29 20:33:44.000000000 +0200
+++ new/CommonMark-0.7.4/.gitignore     2017-08-05 19:28:59.000000000 +0200
@@ -78,6 +78,7 @@
 .env
 
 # virtualenv
+ve/
 venv/
 ENV/
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/__init__.py 
new/CommonMark-0.7.4/CommonMark/__init__.py
--- old/CommonMark-0.7.3/CommonMark/__init__.py 2016-08-04 15:18:10.000000000 
+0200
+++ new/CommonMark-0.7.4/CommonMark/__init__.py 2017-08-05 18:33:33.000000000 
+0200
@@ -5,3 +5,4 @@
 from CommonMark.dump import dumpAST, dumpJSON
 from CommonMark.blocks import Parser
 from CommonMark.render.html import HtmlRenderer
+from CommonMark.render.rst import ReStructuredTextRenderer
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/blocks.py 
new/CommonMark-0.7.4/CommonMark/blocks.py
--- old/CommonMark-0.7.3/CommonMark/blocks.py   2017-01-05 19:42:33.000000000 
+0100
+++ new/CommonMark-0.7.4/CommonMark/blocks.py   2017-08-05 19:23:13.000000000 
+0200
@@ -94,8 +94,8 @@
         'padding': None,
         'marker_offset': parser.indent,
     }
-    m = re.match(reBulletListMarker, rest)
-    m2 = re.match(reOrderedListMarker, rest)
+    m = re.search(reBulletListMarker, rest)
+    m2 = re.search(reOrderedListMarker, rest)
     if m:
         data['type'] = 'bullet'
         data['bullet_char'] = m.group()[0]
@@ -320,7 +320,7 @@
             match = indent <= 3 and \
                 len(ln) >= parser.next_nonspace + 1 and \
                 ln[parser.next_nonspace] == container.fence_char and \
-                re.match(reClosingCodeFence, ln[parser.next_nonspace:])
+                re.search(reClosingCodeFence, ln[parser.next_nonspace:])
             if match and len(match.group()) >= container.fence_length:
                 # closing fence - we're at end of line, so we can return
                 parser.finalize(container, parser.line_number)
@@ -448,8 +448,8 @@
     @staticmethod
     def atx_heading(parser, container=None):
         if not parser.indented:
-            m = re.match(reATXHeadingMarker,
-                         parser.current_line[parser.next_nonspace:])
+            m = re.search(reATXHeadingMarker,
+                          parser.current_line[parser.next_nonspace:])
             if m:
                 parser.advance_next_nonspace()
                 parser.advance_offset(len(m.group()), False)
@@ -459,8 +459,10 @@
                 container.level = len(m.group().strip())
                 # remove trailing ###s:
                 container.string_content = re.sub(
-                    r' +#+ *$', '', re.sub(
-                        r'^ *#+ *$', '', parser.current_line[parser.offset:]))
+                    r'[ \t]+#+[ \t]*$', '', re.sub(
+                        r'^[ \t]*#+[ \t]*$',
+                        '',
+                        parser.current_line[parser.offset:]))
                 parser.advance_offset(
                     len(parser.current_line) - parser.offset, False)
                 return 2
@@ -470,7 +472,7 @@
     @staticmethod
     def fenced_code_block(parser, container=None):
         if not parser.indented:
-            m = re.match(
+            m = re.search(
                 reCodeFence,
                 parser.current_line[parser.next_nonspace:])
             if m:
@@ -508,7 +510,7 @@
     @staticmethod
     def setext_heading(parser, container=None):
         if not parser.indented and container.t == 'paragraph':
-            m = re.match(
+            m = re.search(
                 reSetextHeadingLine,
                 parser.current_line[parser.next_nonspace:])
             if m:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/inlines.py 
new/CommonMark-0.7.4/CommonMark/inlines.py
--- old/CommonMark-0.7.3/CommonMark/inlines.py  2017-01-05 19:42:33.000000000 
+0100
+++ new/CommonMark-0.7.4/CommonMark/inlines.py  2017-08-05 19:23:13.000000000 
+0200
@@ -22,8 +22,32 @@
 ESCAPED_CHAR = '\\\\' + common.ESCAPABLE
 
 rePunctuation = re.compile(
-    r'^[\u2000-\u206F\u2E00-\u2E7F\\' + "'" + '!"#\$%&\(\)'
-    r'\*\+,\-\.\/:;<=>\?@\[\]\^_`\{\|\}~]')
+    r'[!"#$%&\'()*+,\-./:;<=>?@\[\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB'
+    r'\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3'
+    r'\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F'
+    r'\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E'
+    r'\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12'
+    r'\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB'
+    r'\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736'
+    r'\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-'
+    r'\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F'
+    r'\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E'
+    r'\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5'
+    r'\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC'
+    r'\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011'
+    r'\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673'
+    r'\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E'
+    r'\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0'
+    r'\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63'
+    r'\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B'
+    r'\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-'
+    r'\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58'
+    r'\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D'
+    r'\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD'
+    r'\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7'
+    r'\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F'
+    r'\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]'
+)
 
 reLinkTitle = re.compile(
     '^(?:"(' + ESCAPED_CHAR + '|[^"\\x00])*"' +
@@ -184,7 +208,7 @@
             self.pos += 1
             node = Node('linebreak', None)
             block.append_child(node)
-        elif subjchar and re.match(reEscapable, subjchar):
+        elif subjchar and re.search(reEscapable, subjchar):
             block.append_child(text(subjchar))
             self.pos += 1
         else:
@@ -258,21 +282,22 @@
             c_after = '\n'
 
         # Python 2 doesn't recognize '\xa0' as whitespace
-        after_is_whitespace = re.match(reUnicodeWhitespaceChar, c_after) or \
+        after_is_whitespace = re.search(reUnicodeWhitespaceChar, c_after) or \
             c_after == '\xa0'
-        after_is_punctuation = re.match(rePunctuation, c_after)
-        before_is_whitespace = re.match(reUnicodeWhitespaceChar, c_before) or \
+        after_is_punctuation = re.search(rePunctuation, c_after)
+        before_is_whitespace = re.search(
+            reUnicodeWhitespaceChar, c_before) or \
             c_before == '\xa0'
-        before_is_punctuation = re.match(rePunctuation, c_before)
+        before_is_punctuation = re.search(rePunctuation, c_before)
 
         left_flanking = not after_is_whitespace and \
-            not (after_is_punctuation and
-                 not before_is_whitespace and
-                 not before_is_punctuation)
+            (not after_is_punctuation or
+             before_is_whitespace or
+             before_is_punctuation)
         right_flanking = not before_is_whitespace and \
-            not (before_is_punctuation and
-                 not after_is_whitespace and
-                 not after_is_punctuation)
+            (not before_is_punctuation or
+             after_is_whitespace or
+             after_is_punctuation)
         if c == '_':
             can_open = left_flanking and \
                 (not right_flanking or before_is_punctuation)
@@ -385,16 +410,9 @@
                     else:
                         # Calculate actual number of delimiters used from
                         # closer
-                        if closer['numdelims'] < 3 or opener['numdelims'] < 3:
-                            if closer['numdelims'] <= opener['numdelims']:
-                                use_delims = closer['numdelims']
-                            else:
-                                use_delims = opener['numdelims']
-                        else:
-                            if closer['numdelims'] % 2 == 0:
-                                use_delims = 2
-                            else:
-                                use_delims = 1
+                        use_delims = 2 if (
+                            closer['numdelims'] >= 2 and
+                            opener['numdelims'] >= 2) else 1
 
                         opener_inl = opener.get('node')
                         closer_inl = closer.get('node')
@@ -502,7 +520,7 @@
                     else:
                         self.pos += 1
                         openparens -= 1
-                elif re.match(reWhitespaceChar, c):
+                elif re.search(reWhitespaceChar, c):
                     break
                 else:
                     self.pos += 1
@@ -518,8 +536,10 @@
         Attempt to parse a link label, returning number of
         characters parsed.
         """
+        # Note: our regex will allow something of form [..\];
+        # we disallow it here rather than using lookahead in the regex:
         m = self.match(reLinkLabel)
-        if m is None or len(m) > 1001 or re.match(r'\[\s+\]', m):
+        if m is None or len(m) > 1001 or re.search(r'([^\\]\\\]$|\[\n\]$)', m):
             return 0
         else:
             return len(m)
@@ -601,7 +621,7 @@
             dest = self.parseLinkDestination()
             if dest is not None and self.spnl():
                 # make sure there's a space before the title
-                if re.match(reWhitespaceChar, self.subject[self.pos-1]):
+                if re.search(reWhitespaceChar, self.subject[self.pos-1]):
                     title = self.parseLinkTitle()
                 if self.spnl() and self.peek() == ')':
                     self.pos += 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/main.py 
new/CommonMark-0.7.4/CommonMark/main.py
--- old/CommonMark-0.7.3/CommonMark/main.py     2016-08-04 15:18:10.000000000 
+0200
+++ new/CommonMark-0.7.4/CommonMark/main.py     2017-08-05 18:33:33.000000000 
+0200
@@ -14,6 +14,7 @@
 from CommonMark.blocks import Parser
 from CommonMark.dump import dumpAST, dumpJSON
 from CommonMark.render.html import HtmlRenderer
+from CommonMark.render.rst import ReStructuredTextRenderer
 
 
 def commonmark(text, format="html"):
@@ -26,7 +27,7 @@
     """
     parser = Parser()
     ast = parser.parse(text)
-    if format not in ["html", "json", "ast"]:
+    if format not in ["html", "json", "ast", "rst"]:
         raise ValueError("format must be 'html', 'json' or 'ast'")
     if format == "html":
         renderer = HtmlRenderer()
@@ -35,3 +36,6 @@
         return dumpJSON(ast)
     if format == "ast":
         return dumpAST(ast)
+    if format == "rst":
+        renderer = ReStructuredTextRenderer()
+        return renderer.render(ast)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/node.py 
new/CommonMark-0.7.4/CommonMark/node.py
--- old/CommonMark-0.7.3/CommonMark/node.py     2016-08-04 15:18:10.000000000 
+0200
+++ new/CommonMark-0.7.4/CommonMark/node.py     2017-08-05 19:23:13.000000000 
+0200
@@ -10,7 +10,7 @@
 
 
 def is_container(node):
-    return (re.match(reContainer, node.t) is not None)
+    return (re.search(reContainer, node.t) is not None)
 
 
 class NodeWalker(object):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/render/html.py 
new/CommonMark-0.7.4/CommonMark/render/html.py
--- old/CommonMark-0.7.3/CommonMark/render/html.py      2016-08-04 
15:18:10.000000000 +0200
+++ new/CommonMark-0.7.4/CommonMark/render/html.py      2017-08-05 
19:23:13.000000000 +0200
@@ -14,8 +14,8 @@
 
 
 def potentially_unsafe(url):
-    return re.match(reUnsafeProtocol, url) and \
-        (not re.match(reSafeDataProtocol, url))
+    return re.search(reUnsafeProtocol, url) and \
+        (not re.search(reSafeDataProtocol, url))
 
 
 class HtmlRenderer(Renderer):
@@ -29,6 +29,9 @@
         self.last_out = '\n'
         self.options = options
 
+    def escape(self, text, preserve_entities):
+        return escape_xml(text, preserve_entities)
+
     def tag(self, name, attrs=None, selfclosing=None):
         """Helper function to produce an HTML tag."""
         if self.disable_tags > 0:
@@ -62,10 +65,10 @@
         if entering:
             if not (self.options.get('safe') and
                     potentially_unsafe(node.destination)):
-                attrs.append(['href', escape_xml(node.destination, True)])
+                attrs.append(['href', self.escape(node.destination, True)])
 
             if node.title:
-                attrs.append(['title', escape_xml(node.title, True)])
+                attrs.append(['title', self.escape(node.title, True)])
 
             self.tag('a', attrs)
         else:
@@ -79,14 +82,14 @@
                     self.lit('<img src="" alt="')
                 else:
                     self.lit('<img src="' +
-                             escape_xml(node.destination, True) +
+                             self.escape(node.destination, True) +
                              '" alt="')
             self.disable_tags += 1
         else:
             self.disable_tags -= 1
             if self.disable_tags == 0:
                 if node.title:
-                    self.lit('" title="' + escape_xml(node.title, True))
+                    self.lit('" title="' + self.escape(node.title, True))
                 self.lit('" />')
 
     def emph(self, node, entering):
@@ -129,7 +132,7 @@
         attrs = self.attrs(node)
         if len(info_words) > 0 and len(info_words[0]) > 0:
             attrs.append(['class', 'language-' +
-                          escape_xml(info_words[0], True)])
+                          self.escape(info_words[0], True)])
 
         self.cr()
         self.tag('pre')
@@ -211,7 +214,7 @@
     # Helper methods #
 
     def out(self, s):
-        self.lit(escape_xml(s, False))
+        self.lit(self.escape(s, False))
 
     def attrs(self, node):
         att = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/render/rst.py 
new/CommonMark-0.7.4/CommonMark/render/rst.py
--- old/CommonMark-0.7.3/CommonMark/render/rst.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/CommonMark-0.7.4/CommonMark/render/rst.py       2017-08-05 
18:33:33.000000000 +0200
@@ -0,0 +1,159 @@
+from __future__ import unicode_literals
+
+
+from CommonMark.render.renderer import Renderer
+
+
+class ReStructuredTextRenderer(Renderer):
+    """
+    Render reStructuredText from Markdown
+
+    Example:
+
+    .. code:: python
+
+        import CommonMark
+
+        parser = CommonMark.Parser()
+        ast = parser.parse('Hello `inline code` example')
+
+        renderer = CommonMark.ReStructuredTextRenderer()
+        rst = renderer.render(ast)
+        print(rst)  # Hello ``inline code`` example
+    """
+    def __init__(self, indent_char=' '):
+        self.indent_char = indent_char
+        self.indent_length = 0
+
+    def lit(self, s):
+        if s == '\n':
+            indent = ''  # Avoid whitespace if we're just adding a newline
+        elif self.last_out != '\n':
+            indent = ''  # Don't indent if we're in the middle of a line
+        else:
+            indent = self.indent_char * self.indent_length
+
+        return super(ReStructuredTextRenderer, self).lit(indent + s)
+
+    def cr(self):
+        self.lit('\n')
+
+    def indent_lines(self, literal, indent_length=4):
+        indent = self.indent_char * indent_length
+        new_lines = []
+
+        for line in literal.splitlines():
+            new_lines.append(indent + line)
+
+        return '\n'.join(new_lines)
+
+    # Nodes
+
+    def document(self, node, entering):
+        pass
+
+    def softbreak(self, node, entering):
+        self.cr()
+
+    def linebreak(self, node, entering):
+        self.cr()
+        self.cr()
+
+    def text(self, node, entering):
+        self.out(node.literal)
+
+    def emph(self, node, entering):
+        self.out('*')
+
+    def strong(self, node, entering):
+        self.out('**')
+
+    def paragraph(self, node, entering):
+        if node.parent.t == 'item':
+            pass
+        else:
+            self.cr()
+
+    def link(self, node, entering):
+        if entering:
+            self.out('`')
+        else:
+            self.out(' <%s>`_' % node.destination)
+
+    def image(self, node, entering):
+        directive = '.. image:: ' + node.destination
+
+        if entering:
+            self.out(directive)
+            self.cr()
+            self.indent_length += 4
+            self.out(':alt: ')
+        else:
+            self.indent_length -= 4
+
+    def code(self, node, entering):
+        self.out('``')
+        self.out(node.literal)
+        self.out('``')
+
+    def code_block(self, node, entering):
+        directive = '.. code::'
+        language_name = None
+
+        info_words = node.info.split() if node.info else []
+        if len(info_words) > 0 and len(info_words[0]) > 0:
+            language_name = info_words[0]
+
+        if language_name:
+            directive += ' ' + language_name
+
+        self.cr()
+        self.out(directive)
+        self.cr()
+        self.cr()
+        self.out(self.indent_lines(node.literal))
+        self.cr()
+
+    def list(self, node, entering):
+        if entering:
+            self.cr()
+
+    def item(self, node, entering):
+        tagname = '*' if node.list_data['type'] == 'bullet' else '#.'
+
+        if entering:
+            self.out(tagname + ' ')
+        else:
+            self.cr()
+
+    def block_quote(self, node, entering):
+        if entering:
+            self.indent_length += 4
+        else:
+            self.indent_length -= 4
+
+    def heading(self, node, entering):
+        heading_chars = [
+            '#',
+            '*',
+            '=',
+            '-',
+            '^',
+            '"'
+        ]
+
+        try:
+            heading_char = heading_chars[node.level-1]
+        except IndexError:
+            # Default to the last level if we're in too deep
+            heading_char = heading_chars[-1]
+
+        heading_length = len(node.first_child.literal)
+        banner = heading_char * heading_length
+
+        if entering:
+            self.cr()
+        else:
+            self.cr()
+            self.out(banner)
+            self.cr()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark/tests/rst_tests.py 
new/CommonMark-0.7.4/CommonMark/tests/rst_tests.py
--- old/CommonMark-0.7.3/CommonMark/tests/rst_tests.py  1970-01-01 
01:00:00.000000000 +0100
+++ new/CommonMark-0.7.4/CommonMark/tests/rst_tests.py  2017-08-05 
18:33:33.000000000 +0200
@@ -0,0 +1,172 @@
+import unittest
+
+import CommonMark
+
+
+class TestCommonmark(unittest.TestCase):
+    def setUp(self):
+        self.parser = CommonMark.Parser()
+        self.renderer = CommonMark.ReStructuredTextRenderer()
+
+    def render_rst(self, test_str):
+        ast = self.parser.parse(test_str)
+        rst = self.renderer.render(ast)
+
+        return rst
+
+    def assertEqualRender(self, src_markdown, expected_rst):
+        rendered_rst = self.render_rst(src_markdown)
+        self.assertEqual(rendered_rst, expected_rst)
+
+    def test_strong(self):
+        src_markdown = 'Hello **Strong**'
+        expected_rst = '\nHello **Strong**\n'
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_emphasis(self):
+        src_markdown = 'Hello *Emphasis*'
+        expected_rst = '\nHello *Emphasis*\n'
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_paragraph(self):
+        src_markdown = 'Hello paragraph'
+        expected_rst = '\nHello paragraph\n'
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_link(self):
+        src_markdown = '[Link](http://example.com)'
+        expected_rst = '\n`Link <http://example.com>`_\n'
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_image(self):
+        src_markdown = '![Image](http://placekitten.com/100/100)'
+        expected_rst = """
+.. image:: http://placekitten.com/100/100
+    :alt: Image
+"""
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_code(self):
+        src_markdown = 'Test `inline code` with backticks'
+        expected_rst = '\nTest ``inline code`` with backticks\n'
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_code_block(self):
+        src_markdown = """
+```python
+# code block
+print '3 backticks or'
+print 'indent 4 spaces'
+```
+"""
+        expected_rst = """
+.. code:: python
+
+    # code block
+    print '3 backticks or'
+    print 'indent 4 spaces'
+"""
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_unordered_list(self):
+        src_markdown = """
+This is a list:
+* List item
+* List item
+* List item
+"""
+        expected_rst = """
+This is a list:
+
+* List item
+* List item
+* List item
+"""
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_ordered_list(self):
+        src_markdown = """
+This is a ordered list:
+1. One
+2. Two
+3. Three
+"""
+        expected_rst = """
+This is a ordered list:
+
+#. One
+#. Two
+#. Three
+"""
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_block_quote(self):
+        src_markdown = """
+Before the blockquote:
+
+> The blockquote
+
+After the blockquote
+"""
+        expected_rst = """
+Before the blockquote:
+
+    The blockquote
+
+After the blockquote
+"""
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_heading(self):
+        src_markdown = '''
+# Heading 1
+
+## Heading 2
+
+### Heading 3
+
+#### Heading 4
+
+##### Heading 5
+
+###### Heading 6
+'''
+        expected_rst = '''
+Heading 1
+#########
+
+Heading 2
+*********
+
+Heading 3
+=========
+
+Heading 4
+---------
+
+Heading 5
+^^^^^^^^^
+
+Heading 6
+"""""""""
+'''
+        self.assertEqualRender(src_markdown, expected_rst)
+
+    def test_multiple_paragraphs(self):
+        src_markdown = '''
+Start of first paragraph that
+continues on a new line
+
+This is the second paragraph
+'''
+        expected_rst = '''
+Start of first paragraph that
+continues on a new line
+
+This is the second paragraph
+'''
+        self.assertEqualRender(src_markdown, expected_rst)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark.egg-info/PKG-INFO 
new/CommonMark-0.7.4/CommonMark.egg-info/PKG-INFO
--- old/CommonMark-0.7.3/CommonMark.egg-info/PKG-INFO   2017-01-05 
19:49:57.000000000 +0100
+++ new/CommonMark-0.7.4/CommonMark.egg-info/PKG-INFO   2017-08-05 
19:34:09.000000000 +0200
@@ -1,11 +1,11 @@
 Metadata-Version: 1.1
 Name: CommonMark
-Version: 0.7.3
+Version: 0.7.4
 Summary: Python parser for the CommonMark Markdown spec
 Home-page: https://github.com/rtfd/CommonMark-py
 Author: Nik Nyby
 Author-email: [email protected]
-License: BSD License
+License: BSD-3-Clause
 Description: UNKNOWN
 Keywords: markup,markdown,commonmark
 Platform: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/CommonMark.egg-info/SOURCES.txt 
new/CommonMark-0.7.4/CommonMark.egg-info/SOURCES.txt
--- old/CommonMark-0.7.3/CommonMark.egg-info/SOURCES.txt        2017-01-05 
19:49:57.000000000 +0100
+++ new/CommonMark-0.7.4/CommonMark.egg-info/SOURCES.txt        2017-08-05 
19:34:09.000000000 +0200
@@ -24,6 +24,8 @@
 CommonMark/render/__init__.py
 CommonMark/render/html.py
 CommonMark/render/renderer.py
+CommonMark/render/rst.py
 CommonMark/tests/__init__.py
+CommonMark/tests/rst_tests.py
 CommonMark/tests/run_spec_tests.py
 CommonMark/tests/unit_tests.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/PKG-INFO 
new/CommonMark-0.7.4/PKG-INFO
--- old/CommonMark-0.7.3/PKG-INFO       2017-01-05 19:49:57.000000000 +0100
+++ new/CommonMark-0.7.4/PKG-INFO       2017-08-05 19:34:09.000000000 +0200
@@ -1,11 +1,11 @@
 Metadata-Version: 1.1
 Name: CommonMark
-Version: 0.7.3
+Version: 0.7.4
 Summary: Python parser for the CommonMark Markdown spec
 Home-page: https://github.com/rtfd/CommonMark-py
 Author: Nik Nyby
 Author-email: [email protected]
-License: BSD License
+License: BSD-3-Clause
 Description: UNKNOWN
 Keywords: markup,markdown,commonmark
 Platform: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/README.rst 
new/CommonMark-0.7.4/README.rst
--- old/CommonMark-0.7.3/README.rst     2017-01-05 19:48:02.000000000 +0100
+++ new/CommonMark-0.7.4/README.rst     2017-08-05 19:28:59.000000000 +0200
@@ -1,7 +1,7 @@
 CommonMark-py
 =============
 
-Pure Python port of `jgm <https://github.com/jgm>`__'s
+CommonMark-py is a pure Python port of `jgm <https://github.com/jgm>`__'s
 `commonmark.js <https://github.com/jgm/commonmark.js>`__, a
 Markdown parser and renderer for the
 `CommonMark <http://commonmark.org>`__ specification, using only native
@@ -9,14 +9,10 @@
 stable we will release the first ``1.0`` version and attempt to keep up
 to date with changes in ``commonmark.js``.
 
-We are currently at the same development stage (actually a bit ahead
-because we have implemented HTML entity conversion and href URL
-escaping) as ``commonmark.js``. Since Python versions pre-3.4 use outdated
-(i.e. not HTML5 spec) entity conversion, I've converted the 3.4
-implementation into a single file, ``entitytrans.py`` which so far seems
-to work (all tests pass on 2.6, 2.7, 3.3, 3.4, and 3.5).
+CommonMark-py is tested against the CommonMark spec with Python versions
+2.6, 2.7, 3.3, 3.4, 3.5, and 3.6.
 
-**Current version:** 0.7.3
+**Current version:** 0.7.4
 
 |Build Status| |Doc Link|
 
@@ -107,7 +103,7 @@
 
 ::
 
-    $ python run_spec_tests.py -h
+    $ ./venv/bin/python CommonMark/tests/run_spec_tests.py -h
     usage: run_spec_tests.py [-h] [-t T] [-p] [-f] [-i] [-d] [-np] [-s]
 
     script to run the CommonMark specification tests against the CommonMark.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/setup.cfg 
new/CommonMark-0.7.4/setup.cfg
--- old/CommonMark-0.7.3/setup.cfg      2017-01-05 19:49:57.000000000 +0100
+++ new/CommonMark-0.7.4/setup.cfg      2017-08-05 19:34:09.000000000 +0200
@@ -5,7 +5,7 @@
 universal = 1
 
 [egg_info]
-tag_svn_revision = 0
 tag_build = 
 tag_date = 0
+tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/setup.py 
new/CommonMark-0.7.4/setup.py
--- old/CommonMark-0.7.3/setup.py       2017-01-05 19:48:02.000000000 +0100
+++ new/CommonMark-0.7.4/setup.py       2017-08-05 19:28:59.000000000 +0200
@@ -21,8 +21,8 @@
 setup(
     name="CommonMark",
     packages=find_packages(exclude=['tests']),
-    version="0.7.3",
-    license="BSD License",
+    version="0.7.4",
+    license="BSD-3-Clause",
     description="Python parser for the CommonMark Markdown spec",
     author="Bibek Kafle <[email protected]>, " +
     "Roland Shoemaker <[email protected]>",
@@ -41,8 +41,8 @@
         'future',
     ],
     tests_require=[
-        'flake8==2.6.2',
-        'hypothesis',
+        'flake8==3.4.0',
+        'hypothesis==3.7.1',
         # For python 2.6
         'hypothesislegacysupport',
     ],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CommonMark-0.7.3/spec.txt 
new/CommonMark-0.7.4/spec.txt
--- old/CommonMark-0.7.3/spec.txt       2017-01-05 19:42:33.000000000 +0100
+++ new/CommonMark-0.7.4/spec.txt       2017-08-05 19:23:13.000000000 +0200
@@ -1,8 +1,8 @@
 ---
 title: CommonMark Spec
 author: John MacFarlane
-version: 0.27
-date: '2016-11-18'
+version: 0.28
+date: '2017-08-01'
 license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
 ...
 
@@ -11,10 +11,12 @@
 ## What is Markdown?
 
 Markdown is a plain text format for writing structured documents,
-based on conventions used for indicating formatting in email and
-usenet posts.  It was developed in 2004 by John Gruber, who wrote
-the first Markdown-to-HTML converter in Perl, and it soon became
-ubiquitous.  In the next decade, dozens of implementations were
+based on conventions for indicating formatting in email
+and usenet posts.  It was developed by John Gruber (with
+help from Aaron Swartz) and released in 2004 in the form of a
+[syntax description](http://daringfireball.net/projects/markdown/syntax)
+and a Perl script (`Markdown.pl`) for converting Markdown to
+HTML.  In the next decade, dozens of implementations were
 developed in many languages.  Some extended the original
 Markdown syntax with conventions for footnotes, tables, and
 other document elements.  Some allowed Markdown documents to be
@@ -312,7 +314,7 @@
 characters].
 
 A [Unicode whitespace character](@) is
-any code point in the Unicode `Zs` class, or a tab (`U+0009`),
+any code point in the Unicode `Zs` general category, or a tab (`U+0009`),
 carriage return (`U+000D`), newline (`U+000A`), or form feed
 (`U+000C`).
 
@@ -331,7 +333,7 @@
 
 A [punctuation character](@) is an [ASCII
 punctuation character] or anything in
-the Unicode classes `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`.
+the general Unicode categories  `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`.
 
 ## Tabs
 
@@ -402,8 +404,8 @@
 Normally the `>` that begins a block quote may be followed
 optionally by a space, which is not considered part of the
 content.  In the following case `>` is followed by a tab,
-which is treated as if it were expanded into spaces.
-Since one of theses spaces is considered part of the
+which is treated as if it were expanded into three spaces.
+Since one of these spaces is considered part of the
 delimiter, `foo` is considered to be indented six spaces
 inside the block quote context, so we get an indented
 code block starting with two spaces.
@@ -481,7 +483,7 @@
 quotations, lists, headings, rules, and code blocks.  Some blocks (like
 block quotes and list items) contain other blocks; others (like
 headings and paragraphs) contain [inline](@) content---text,
-links, emphasized text, images, code, and so on.
+links, emphasized text, images, code spans, and so on.
 
 ## Precedence
 
@@ -1643,6 +1645,15 @@
 </code></pre>
 ````````````````````````````````
 
+Fewer than three backticks is not enough:
+
+```````````````````````````````` example
+``
+foo
+``
+.
+<p><code>foo</code></p>
+````````````````````````````````
 
 The closing code fence must use the same character as the opening
 fence:
@@ -2031,6 +2042,37 @@
 or the end of the line.\
 **End condition:** line is followed by a [blank line].
 
+HTML blocks continue until they are closed by their appropriate
+[end condition], or the last line of the document or other [container block].
+This means any HTML **within an HTML block** that might otherwise be recognised
+as a start condition will be ignored by the parser and passed through as-is,
+without changing the parser's state.
+
+For instance, `<pre>` within a HTML block started by `<table>` will not affect
+the parser state; as the HTML block was started in by start condition 6, it
+will end at any blank line. This can be surprising:
+
+```````````````````````````````` example
+<table><tr><td>
+<pre>
+**Hello**,
+
+_world_.
+</pre>
+</td></tr></table>
+.
+<table><tr><td>
+<pre>
+**Hello**,
+<p><em>world</em>.
+</pre></p>
+</td></tr></table>
+````````````````````````````````
+
+In this case, the HTML block is terminated by the newline — the `**hello**`
+text remains verbatim — and regular parsing resumes, with a paragraph,
+emphasised `world` and inline and block HTML following.
+
 All types of [HTML blocks] except type 7 may interrupt
 a paragraph.  Blocks of type 7 may not interrupt a paragraph.
 (This restriction is intended to prevent unwanted interpretation
@@ -3637,11 +3679,15 @@
     If the list item is ordered, then it is also assigned a start
     number, based on the ordered list marker.
 
-    Exceptions: When the first list item in a [list] interrupts
-    a paragraph---that is, when it starts on a line that would
-    otherwise count as [paragraph continuation text]---then (a)
-    the lines *Ls* must not begin with a blank line, and (b) if
-    the list item is ordered, the start number must be 1.
+    Exceptions:
+
+    1. When the first list item in a [list] interrupts
+       a paragraph---that is, when it starts on a line that would
+       otherwise count as [paragraph continuation text]---then (a)
+       the lines *Ls* must not begin with a blank line, and (b) if
+       the list item is ordered, the start number must be 1.
+    2. If any line is a [thematic break][thematic breaks] then
+       that line is not a list item.
 
 For example, let *Ls* be the lines
 
@@ -5796,6 +5842,15 @@
 <p>`foo</p>
 ````````````````````````````````
 
+The following case also illustrates the need for opening and
+closing backtick strings to be equal in length:
+
+```````````````````````````````` example
+`foo``bar``
+.
+<p>`foo<code>bar</code></p>
+````````````````````````````````
+
 
 ## Emphasis and strong emphasis
 
@@ -5845,19 +5900,20 @@
 
 First, some definitions.  A [delimiter run](@) is either
 a sequence of one or more `*` characters that is not preceded or
-followed by a `*` character, or a sequence of one or more `_`
-characters that is not preceded or followed by a `_` character.
+followed by a non-backslash-escaped `*` character, or a sequence
+of one or more `_` characters that is not preceded or followed by
+a non-backslash-escaped `_` character.
 
 A [left-flanking delimiter run](@) is
 a [delimiter run] that is (a) not followed by [Unicode whitespace],
-and (b) either not followed by a [punctuation character], or
+and (b) not followed by a [punctuation character], or
 preceded by [Unicode whitespace] or a [punctuation character].
 For purposes of this definition, the beginning and the end of
 the line count as Unicode whitespace.
 
 A [right-flanking delimiter run](@) is
 a [delimiter run] that is (a) not preceded by [Unicode whitespace],
-and (b) either not preceded by a [punctuation character], or
+and (b) not preceded by a [punctuation character], or
 followed by [Unicode whitespace] or a [punctuation character].
 For purposes of this definition, the beginning and the end of
 the line count as Unicode whitespace.
@@ -5936,7 +5992,7 @@
 7.  A double `**` [can close strong emphasis](@)
     iff it is part of a [right-flanking delimiter run].
 
-8.  A double `__` [can close strong emphasis]
+8.  A double `__` [can close strong emphasis] iff
     it is part of a [right-flanking delimiter run]
     and either (a) not part of a [left-flanking delimiter run]
     or (b) part of a [left-flanking delimiter run]
@@ -5976,8 +6032,8 @@
     an interpretation `<strong>...</strong>` is always preferred to
     `<em><em>...</em></em>`.
 
-14. An interpretation `<strong><em>...</em></strong>` is always
-    preferred to `<em><strong>..</strong></em>`.
+14. An interpretation `<em><strong>...</strong></em>` is always
+    preferred to `<strong><em>...</em></strong>`.
 
 15. When two potential emphasis or strong emphasis spans overlap,
     so that the second begins before the first ends and ends after
@@ -7000,14 +7056,14 @@
 ```````````````````````````````` example
 ***foo***
 .
-<p><strong><em>foo</em></strong></p>
+<p><em><strong>foo</strong></em></p>
 ````````````````````````````````
 
 
 ```````````````````````````````` example
 _____foo_____
 .
-<p><strong><strong><em>foo</em></strong></strong></p>
+<p><em><strong><strong>foo</strong></strong></em></p>
 ````````````````````````````````
 
 
@@ -7148,7 +7204,9 @@
 - a nonempty sequence of characters that does not include
   ASCII space or control characters, and includes parentheses
   only if (a) they are backslash-escaped or (b) they are part of
-  a balanced pair of unescaped parentheses.
+  a balanced pair of unescaped parentheses.  (Implementations
+  may impose limits on parentheses nesting to avoid performance
+  issues, but at least three levels of nesting should be supported.)
 
 A [link title](@)  consists of either
 
@@ -7254,7 +7312,7 @@
 <p><a href="(foo)">link</a></p>
 ````````````````````````````````
 
-Any number parentheses are allowed without escaping, as long as they are
+Any number of parentheses are allowed without escaping, as long as they are
 balanced:
 
 ```````````````````````````````` example
@@ -7560,13 +7618,16 @@
 A [link label](@)  begins with a left bracket (`[`) and ends
 with the first right bracket (`]`) that is not backslash-escaped.
 Between these brackets there must be at least one [non-whitespace character].
-Unescaped square bracket characters are not allowed in
-[link labels].  A link label can have at most 999
-characters inside the square brackets.
+Unescaped square bracket characters are not allowed inside the
+opening and closing square brackets of [link labels].  A link
+label can have at most 999 characters inside the square
+brackets.
 
 One label [matches](@)
 another just in case their normalized forms are equal.  To normalize a
-label, perform the *Unicode case fold* and collapse consecutive internal
+label, strip off the opening and closing brackets,
+perform the *Unicode case fold*, strip leading and trailing
+[whitespace] and collapse consecutive internal
 [whitespace] to a single space.  If there are multiple
 matching reference link definitions, the one that comes first in the
 document is used.  (It is desirable in such cases to emit a warning.)
@@ -8319,11 +8380,11 @@
 ````````````````````````````````
 
 
-If you just want bracketed text, you can backslash-escape the
-opening `!` and `[`:
+If you just want a literal `!` followed by bracketed text, you can
+backslash-escape the opening `[`:
 
 ```````````````````````````````` example
-\!\[foo]
+!\[foo]
 
 [foo]: /url "title"
 .


Reply via email to