diff options
author | JensDiemer <git@jensdiemer.de> | 2020-01-13 18:26:25 +0100 |
---|---|---|
committer | JensDiemer <git@jensdiemer.de> | 2020-01-13 19:22:21 +0100 |
commit | 7ec315292794f8a210b9dd759d4991ed9363d73e (patch) | |
tree | 7cf71d89291735dffd265d2fb64e7d972d247909 | |
parent | c33fac617ada1a97b4f60a471f5dcf32e992fe75 (diff) | |
download | creole-7ec315292794f8a210b9dd759d4991ed9363d73e.tar.gz |
modernize project:poetry
* remove python v2 support code
* reformat code with black
* use python f-strings
* use poetry
* add a Makefile
* add github actions
* nose -> pytest
56 files changed, 2272 insertions, 1914 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..40bd47a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +# see http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{html,css,js}] +insert_final_newline = false + +[*.py] +line_length = 119 + +[{Makefile,**.mk}] +indent_style = tab +insert_final_newline = false + +[*.{yml}] +indent_style = space +indent_size = 2 @@ -0,0 +1,4 @@ +[flake8] +exclude = .pytest_cache, python_creole.egg-info +ignore = E402 +max-line-length = 119 diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml new file mode 100644 index 0000000..d1c6fd7 --- /dev/null +++ b/.github/workflows/pythonapp.yml @@ -0,0 +1,43 @@ +name: build + +on: [push] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + + - name: Install package + run: make install + + - name: List installed packages + run: poetry run pip freeze + + - name: Run linters + run: make lint + + test: + needs: lint + runs-on: ${{ matrix.platform }} + strategy: + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + python-version: [3.6, 3.7, 3.8] + steps: + - uses: actions/checkout@v1 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + + - name: Install package + run: make install + + - name: Run unit tests + run: make test @@ -5,4 +5,6 @@ /dist /build -.idea
\ No newline at end of file +.idea +/poetry.lock +/.coverage diff --git a/.noserc b/.noserc deleted file mode 100644 index e5d8b6d..0000000 --- a/.noserc +++ /dev/null @@ -1,5 +0,0 @@ -[nosetests] -verbose=True -verbosity=2 -detailed-errors=1 -with-doctest=1
\ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 9a9db2a..1b38fc6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,26 +3,20 @@ language: python python: - - "2.7" - - "3.5" - "3.6" - "3.7" - "3.8" - - "pypy" - "pypy3" install: - - pip install --upgrade pip - - pip install nose textile docutils pygments coveralls - - pip install . + - make install + - poetry run pip freeze script: - - coverage run ./setup.py nosetests + - make test + - make lint after_success: - coveralls # https://github.com/codecov/codecov-bash - - bash <(curl -s https://codecov.io/bash) - -notifications: - irc: "irc.freenode.org#pylucid" + - bash <(curl -s https://codecov.io/bas diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d16c2a9 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +.PHONY: help install lint fix test release + +VERSION := $$(poetry version | sed -n 's/contxt-sdk //p') + +help: ## List all commands + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z -]+:.*?## / {printf "\033[36m%-10s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +install: + pip install poetry + poetry install + +lint: ## Run code formatters and linter + poetry run isort --check-only --recursive creole + poetry run black --line-length=119 --check creole + poetry run flake8 creole + +fix: ## Fix code formatting + poetry run flynt --line_length=119 creole + poetry run isort --apply --recursive creole + poetry run black --line-length=119 creole + +test: ## Run unit tests + poetry run pytest + +release: ## Release new version [usage: v=rule] + # Update pyproject and changelog + poetry version $(v) + sed -i "" "s/\[Unreleased\]/\[$(VERSION)\] - $(shell date +%F)/" CHANGELOG.md + # Create commit and tag + git commit pyproject.toml CHANGELOG.md -m "Bump version to $(VERSION)" && git tag "v$(VERSION)" + git push && git push --tags + # Publish to pypi + poetry publish --build
\ No newline at end of file diff --git a/creole/__init__.py b/creole/__init__.py index 6594f9d..6a4bf6b 100644 --- a/creole/__init__.py +++ b/creole/__init__.py @@ -7,10 +7,10 @@ :homepage: http://code.google.com/p/python-creole/ - + :sourcecode: http://github.com/jedie/python-creole - + :PyPi: http://pypi.python.org/pypi/python-creole/ @@ -18,48 +18,55 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import warnings from creole.emitter.creol2html_emitter import HtmlEmitter -from creole.parser.creol2html_parser import CreoleParser from creole.emitter.html2creole_emitter import CreoleEmitter from creole.emitter.html2rest_emitter import ReStructuredTextEmitter from creole.emitter.html2textile_emitter import TextileEmitter +from creole.parser.creol2html_parser import CreoleParser from creole.parser.html_parser import HtmlParser -from creole.py3compat import TEXT_TYPE __version__ = "1.3.2" -__api__ = "1.0" # Creole 1.0 spec - http://wikicreole.org/ - -VERSION_STRING = __version__ # remove in future -API_STRING = __api__ # remove in future - - -def creole2html(markup_string, debug=False, - parser_kwargs=None, emitter_kwargs=None, - block_rules=None, blog_line_breaks=True, - macros=None, verbose=None, stderr=None, - strict=False, - ): +__api__ = "1.0" # Creole 1.0 spec - http://wikicreole.org/ + +VERSION_STRING = __version__ # remove in future +API_STRING = __api__ # remove in future + + +def creole2html( + markup_string, + debug=False, + parser_kwargs=None, + emitter_kwargs=None, + block_rules=None, + blog_line_breaks=True, + macros=None, + verbose=None, + stderr=None, + strict=False, +): """ convert creole markup into html code >>> creole2html('This is **creole //markup//**!') '<p>This is <strong>creole <i>markup</i></strong>!</p>' - + Info: parser_kwargs and emitter_kwargs are deprecated """ - assert isinstance(markup_string, TEXT_TYPE), "given markup_string must be unicode!" + assert isinstance(markup_string, str), "given markup_string must be unicode!" parser_kwargs2 = { "block_rules": block_rules, "blog_line_breaks": blog_line_breaks, } if parser_kwargs is not None: - warnings.warn("parser_kwargs argument in creole2html would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "parser_kwargs argument in creole2html would be removed in the future!", PendingDeprecationWarning + ) parser_kwargs2.update(parser_kwargs) # Create document tree from creole markup @@ -74,7 +81,9 @@ def creole2html(markup_string, debug=False, "strict": strict, } if emitter_kwargs is not None: - warnings.warn("emitter_kwargs argument in creole2html would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "emitter_kwargs argument in creole2html would be removed in the future!", PendingDeprecationWarning + ) emitter_kwargs2.update(emitter_kwargs) # Build html code from document tree @@ -83,7 +92,7 @@ def creole2html(markup_string, debug=False, def parse_html(html_string, debug=False): """ create the document tree from html code """ - assert isinstance(html_string, TEXT_TYPE), "given html_string must be unicode!" + assert isinstance(html_string, str), "given html_string must be unicode!" h2c = HtmlParser(debug=debug) document_tree = h2c.feed(html_string) @@ -93,13 +102,8 @@ def parse_html(html_string, debug=False): def html2creole( - html_string, - debug=False, - parser_kwargs=None, - emitter_kwargs=None, - unknown_emit=None, - strict=False, - ): + html_string, debug=False, parser_kwargs=None, emitter_kwargs=None, unknown_emit=None, strict=False, +): """ convert html code into creole markup @@ -107,7 +111,9 @@ def html2creole( 'This is **creole //markup//**!' """ if parser_kwargs is not None: - warnings.warn("parser_kwargs argument in html2creole would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "parser_kwargs argument in html2creole would be removed in the future!", PendingDeprecationWarning + ) document_tree = parse_html(html_string, debug=debug) @@ -116,7 +122,9 @@ def html2creole( "strict": strict, } if emitter_kwargs is not None: - warnings.warn("emitter_kwargs argument in html2creole would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "emitter_kwargs argument in html2creole would be removed in the future!", PendingDeprecationWarning + ) emitter_kwargs2.update(emitter_kwargs) # create creole markup from the document tree @@ -124,18 +132,17 @@ def html2creole( return emitter.emit() -def html2textile(html_string, debug=False, - parser_kwargs=None, emitter_kwargs=None, - unknown_emit=None - ): +def html2textile(html_string, debug=False, parser_kwargs=None, emitter_kwargs=None, unknown_emit=None): """ convert html code into textile markup - + >>> html2textile('<p>This is <strong>textile <i>markup</i></strong>!</p>') 'This is *textile __markup__*!' """ if parser_kwargs is not None: - warnings.warn("parser_kwargs argument in html2textile would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "parser_kwargs argument in html2textile would be removed in the future!", PendingDeprecationWarning + ) document_tree = parse_html(html_string, debug=debug) @@ -143,7 +150,9 @@ def html2textile(html_string, debug=False, "unknown_emit": unknown_emit, } if emitter_kwargs is not None: - warnings.warn("emitter_kwargs argument in html2textile would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "emitter_kwargs argument in html2textile would be removed in the future!", PendingDeprecationWarning + ) emitter_kwargs2.update(emitter_kwargs) # create textile markup from the document tree @@ -151,13 +160,10 @@ def html2textile(html_string, debug=False, return emitter.emit() -def html2rest(html_string, debug=False, - parser_kwargs=None, emitter_kwargs=None, - unknown_emit=None - ): +def html2rest(html_string, debug=False, parser_kwargs=None, emitter_kwargs=None, unknown_emit=None): """ convert html code into ReStructuredText markup - + >>> html2rest('<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') 'This is **ReStructuredText** *markup*!' """ @@ -170,7 +176,9 @@ def html2rest(html_string, debug=False, "unknown_emit": unknown_emit, } if emitter_kwargs is not None: - warnings.warn("emitter_kwargs argument in html2rest would be removed in the future!", PendingDeprecationWarning) + warnings.warn( + "emitter_kwargs argument in html2rest would be removed in the future!", PendingDeprecationWarning + ) emitter_kwargs2.update(emitter_kwargs) # create ReStructuredText markup from the document tree @@ -178,10 +186,12 @@ def html2rest(html_string, debug=False, return emitter.emit() - -if __name__ == '__main__': +if __name__ == "__main__": print("runing local doctest...") import doctest - print(doctest.testmod( -# verbose=True - )) + + print( + doctest.testmod( + # verbose=True + ) + ) diff --git a/creole/cmdline.py b/creole/cmdline.py index 82a156e..2b3ff67 100644 --- a/creole/cmdline.py +++ b/creole/cmdline.py @@ -9,12 +9,12 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + + import argparse import codecs -from creole import creole2html, html2creole, html2rest, html2textile -from creole import VERSION_STRING +from creole import VERSION_STRING, creole2html, html2creole, html2rest, html2textile class CreoleCLI(object): @@ -32,11 +32,10 @@ class CreoleCLI(object): ) self.parser.add_argument("sourcefile", help="source file to convert") self.parser.add_argument("destination", help="Output filename") - self.parser.add_argument("--encoding", - default="utf-8", - help="Codec for read/write file (default encoding: utf-8)" + self.parser.add_argument( + "--encoding", default="utf-8", help="Codec for read/write file (default encoding: utf-8)" ) - + args = self.parser.parse_args() sourcefile = args.sourcefile @@ -46,33 +45,35 @@ class CreoleCLI(object): self.convert(sourcefile, destination, encoding) def convert(self, sourcefile, destination, encoding): - print("Convert %r to %r with %s (codec: %s)" % ( - sourcefile, destination, self.convert_func.__name__, encoding - )) - + print(f"Convert {sourcefile!r} to {destination!r} with {self.convert_func.__name__} (codec: {encoding})") + with codecs.open(sourcefile, "r", encoding=encoding) as infile: with codecs.open(destination, "w", encoding=encoding) as outfile: content = infile.read() converted = self.convert_func(content) outfile.write(converted) - print("done. %r created." % destination) + print(f"done. {destination!r} created.") def cli_creole2html(): CreoleCLI(creole2html) + def cli_html2creole(): CreoleCLI(html2creole) - + + def cli_html2rest(): CreoleCLI(html2rest) - + + def cli_html2textile(): CreoleCLI(html2textile) if __name__ == "__main__": import sys + sys.argv += ["../README.creole", "../test.html"] print(sys.argv) cli_creole2html() diff --git a/creole/emitter/creol2html_emitter.py b/creole/emitter/creol2html_emitter.py index 2879f4e..b347e87 100644 --- a/creole/emitter/creol2html_emitter.py +++ b/creole/emitter/creol2html_emitter.py @@ -9,15 +9,15 @@ """ -from __future__ import division, absolute_import, print_function, unicode_literals + import json -from xml.sax.saxutils import escape import sys import traceback +from xml.sax.saxutils import escape from creole.parser.creol2html_parser import CreoleParser -from creole.py3compat import TEXT_TYPE + from creole.shared.utils import string2dict @@ -37,14 +37,12 @@ class TableOfContent(object): if depth is not None: self.max_depth = depth - return '<<toc>>' + return "<<toc>>" def add_headline(self, level, content): """Add the current header to the toc.""" if self.max_depth is None or level <= self.max_depth: - self.headlines.append( - (level, content) - ) + self.headlines.append((level, content)) def flat_list2nest_list(self, flat_list): # this func code based on borrowed code from EyDu, Thanks! @@ -69,14 +67,14 @@ class TableOfContent(object): def nested_headlines2html(self, nested_headlines, level=0): """Convert a python nested list like the one representing the toc to an html equivalent.""" - indent = "\t"*level - if isinstance(nested_headlines, TEXT_TYPE): - return '%s<li><a href="#%s">%s</a></li>\n' % (indent, nested_headlines, nested_headlines) + indent = "\t" * level + if isinstance(nested_headlines, str): + return f'{indent}<li><a href="#{nested_headlines}">{nested_headlines}</a></li>\n' elif isinstance(nested_headlines, list): - html = '%s<ul>\n' % indent + html = f"{indent}<ul>\n" for elt in nested_headlines: html += self.nested_headlines2html(elt, level + 1) - html += '%s</ul>' % indent + html += f"{indent}</ul>" if level > 0: html += "\n" return html @@ -96,12 +94,12 @@ class TableOfContent(object): return document - class HtmlEmitter(object): """ Generate HTML output for the document tree consisting of DocNodes. """ + def __init__(self, root, macros=None, verbose=None, stderr=None, strict=False): self.root = root @@ -132,7 +130,6 @@ class HtmlEmitter(object): self.toc = TableOfContent() self.macros.toc = self.toc - if verbose is None: self.verbose = 1 else: @@ -148,15 +145,15 @@ class HtmlEmitter(object): def get_text(self, node): """Try to emit whatever text is in the node.""" try: - return node.children[0].content or '' + return node.children[0].content or "" except: - return node.content or '' + return node.content or "" def html_escape(self, text): return escape(text) def attr_escape(self, text): - return self.html_escape(text).replace('"', '"') + return self.html_escape(text).replace('"', """) # *_emit methods for emitting nodes of the document: @@ -167,27 +164,22 @@ class HtmlEmitter(object): return self.html_escape(node.content) def separator_emit(self, node): - return '<hr />\n\n' + return "<hr />\n\n" def paragraph_emit(self, node): - return '<p>%s</p>\n' % self.emit_children(node) + return "<p>%s</p>\n" % self.emit_children(node) def _list_emit(self, node, list_type): if node.parent.kind in ("document",): # The first list item - formatter = '' + formatter = "" else: - formatter = '\n' + formatter = "\n" if list_type == "li": - formatter += ( - '%(i)s<%(t)s>%(c)s</%(t)s>' - ) + formatter += "%(i)s<%(t)s>%(c)s</%(t)s>" else: - formatter += ( - '%(i)s<%(t)s>%(c)s\n' - '%(i)s</%(t)s>' - ) + formatter += "%(i)s<%(t)s>%(c)s\n" "%(i)s</%(t)s>" return formatter % { "i": "\t" * node.level, "c": self.emit_children(node), @@ -204,21 +196,21 @@ class HtmlEmitter(object): return self._list_emit(node, list_type="li") def table_emit(self, node): - return '<table>\n%s</table>\n' % self.emit_children(node) + return "<table>\n%s</table>\n" % self.emit_children(node) def table_row_emit(self, node): - return '<tr>\n%s</tr>\n' % self.emit_children(node) + return "<tr>\n%s</tr>\n" % self.emit_children(node) def table_cell_emit(self, node): - return '\t<td>%s</td>\n' % self.emit_children(node) + return "\t<td>%s</td>\n" % self.emit_children(node) def table_head_emit(self, node): - return '\t<th>%s</th>\n' % self.emit_children(node) + return "\t<th>%s</th>\n" % self.emit_children(node) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _typeface(self, node, tag): - return '<%(tag)s>%(data)s</%(tag)s>' % { + return "<%(tag)s>%(data)s</%(tag)s>" % { "tag": tag, "data": self.emit_children(node), } @@ -226,39 +218,42 @@ class HtmlEmitter(object): # TODO: How can we generalize that: def emphasis_emit(self, node): return self._typeface(node, tag="i") + def strong_emit(self, node): return self._typeface(node, tag="strong") + def monospace_emit(self, node): return self._typeface(node, tag="tt") + def superscript_emit(self, node): return self._typeface(node, tag="sup") + def subscript_emit(self, node): return self._typeface(node, tag="sub") + def underline_emit(self, node): return self._typeface(node, tag="u") + def small_emit(self, node): return self._typeface(node, tag="small") + def delete_emit(self, node): return self._typeface(node, tag="del") - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def header_emit(self, node): - header = '<h%d>%s</h%d>' % ( - node.level, self.html_escape(node.content), node.level - ) + header = f"<h{node.level:d}>{self.html_escape(node.content)}</h{node.level:d}>" if self.toc is not None: self.toc.add_headline(node.level, node.content) # add link attribute for toc navigation - header = '<a name="%s">%s</a>' % ( - self.html_escape(node.content), header - ) + header = f'<a name="{self.html_escape(node.content)}">{header}</a>' header += "\n" return header def preformatted_emit(self, node): - return '<pre>%s</pre>' % self.html_escape(node.content) + return "<pre>%s</pre>" % self.html_escape(node.content) def link_emit(self, node): target = node.content @@ -267,8 +262,7 @@ class HtmlEmitter(object): else: inside = self.html_escape(target) - return '<a href="%s">%s</a>' % ( - self.attr_escape(target), inside) + return f'<a href="{self.attr_escape(target)}">{inside}</a>' def image_emit(self, node): target = node.content @@ -283,14 +277,18 @@ class HtmlEmitter(object): width = int(w_str.strip()) height = int(h_str.strip()) return '<img src="%s" title="%s" alt="%s" width="%s" height="%s" />' % ( - self.attr_escape(target), title, title, width, height) + self.attr_escape(target), + title, + title, + width, + height, + ) except: pass - return '<img src="%s" title="%s" alt="%s" />' % ( - self.attr_escape(target), text, text) + return f'<img src="{self.attr_escape(target)}" title="{text}" alt="{text}" />' def macro_emit(self, node): - #print(node.debug()) + # print(node.debug()) macro_name = node.macro_name text = node.content macro = None @@ -301,10 +299,8 @@ class HtmlEmitter(object): except ValueError as e: exc_info = sys.exc_info() return self.error( - "Wrong macro arguments: %s for macro '%s' (maybe wrong macro tag syntax?)" % ( - json.dumps(args), macro_name - ), - exc_info + f"Wrong macro arguments: {json.dumps(args)} for macro '{macro_name}' (maybe wrong macro tag syntax?)", + exc_info, ) macro_kwargs["text"] = text @@ -322,15 +318,12 @@ class HtmlEmitter(object): exc_info = sys.exc_info() if macro == None: - return self.error( - "Macro '%s' doesn't exist" % macro_name, - exc_info - ) + return self.error(f"Macro '{macro_name}' doesn't exist", exc_info) try: result = macro(**macro_kwargs) except TypeError as err: - msg = "Macro '%s' error: %s" % (macro_name, err) + msg = f"Macro '{macro_name}' error: {err}" exc_info = sys.exc_info() if self.verbose > 1: if self.verbose > 2: @@ -339,6 +332,7 @@ class HtmlEmitter(object): # Inject more information about the macro in traceback etype, evalue, etb = exc_info import inspect + try: filename = inspect.getfile(macro) except TypeError: @@ -347,28 +341,26 @@ class HtmlEmitter(object): try: sourceline = inspect.getsourcelines(macro)[0][0].strip() except IOError as err: - evalue = etype("%s (error getting sourceline: %s from %s)" % (evalue, err, filename)) + evalue = etype(f"{evalue} (error getting sourceline: {err} from {filename})") else: - evalue = etype("%s (sourceline: %r from %s)" % (evalue, sourceline, filename)) + evalue = etype(f"{evalue} (sourceline: {sourceline!r} from {filename})") exc_info = etype, evalue, etb return self.error(msg, exc_info) except Exception as err: - return self.error( - "Macro '%s' error: %s" % (macro_name, err), - exc_info=sys.exc_info() - ) + return self.error(f"Macro '{macro_name}' error: {err}", exc_info=sys.exc_info()) - if not isinstance(result, TEXT_TYPE): - msg = "Macro '%s' doesn't return a unicode string!" % macro_name + if not isinstance(result, str): + msg = f"Macro '{macro_name}' doesn't return a unicode string!" if self.verbose > 1: - msg += " - returns: %r, type %r" % (result, type(result)) + msg += f" - returns: {result!r}, type {type(result)!r}" return self.error(msg) if node.kind == "macro_block": result += "\n" return result + macro_inline_emit = macro_emit macro_block_emit = macro_emit @@ -393,16 +385,16 @@ class HtmlEmitter(object): def default_emit(self, node): """Fallback function for emitting unknown nodes.""" - raise NotImplementedError("Node '%s' unknown" % node.kind) + raise NotImplementedError(f"Node '{node.kind}' unknown") def emit_children(self, node): """Emit all the children of a node.""" - return ''.join([self.emit_node(child) for child in node.children]) + return "".join([self.emit_node(child) for child in node.children]) def emit_node(self, node): """Emit a single node.""" - #print("%s_emit: %r" % (node.kind, node.content)) - emit = getattr(self, '%s_emit' % node.kind, self.default_emit) + # print("%s_emit: %r" % (node.kind, node.content)) + emit = getattr(self, f"{node.kind}_emit", self.default_emit) return emit(node) def emit(self): @@ -423,7 +415,7 @@ class HtmlEmitter(object): self.stderr.write(exception) if self.verbose > 0: - return "[Error: %s]\n" % text + return f"[Error: {text}]\n" else: # No error output return "" @@ -441,7 +433,7 @@ if __name__ == "__main__": """ print("-" * 80) -# from creole_alt.creole import CreoleParser + # from creole_alt.creole import CreoleParser p = CreoleParser(txt) document = p.parse() p.debug() diff --git a/creole/emitter/html2creole_emitter.py b/creole/emitter/html2creole_emitter.py index 2e9c31c..34b14b8 100644 --- a/creole/emitter/html2creole_emitter.py +++ b/creole/emitter/html2creole_emitter.py @@ -10,18 +10,19 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + + import posixpath from creole.shared.base_emitter import BaseEmitter - class CreoleEmitter(BaseEmitter): """ Build from a document_tree (html2creole.parser.HtmlParser instance) a creole markup text. """ + def __init__(self, document_tree, strict=False, *args, **kwargs): self.strict = strict super(CreoleEmitter, self).__init__(document_tree, *args, **kwargs) @@ -31,22 +32,23 @@ class CreoleEmitter(BaseEmitter): def emit(self): """Emit the document represented by self.root DOM tree.""" - return self.emit_node(self.root).strip() # FIXME + return self.emit_node(self.root).strip() # FIXME - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def blockdata_pre_emit(self, node): """ pre block -> with newline at the end """ return "{{{%s}}}\n" % self.deentity.replace_all(node.content) + def inlinedata_pre_emit(self, node): """ a pre inline block -> no newline at the end """ return "{{{%s}}}" % self.deentity.replace_all(node.content) def blockdata_pass_emit(self, node): - return "%s\n\n" % node.content + return f"{node.content}\n\n" return node.content - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def p_emit(self, node): result = self.emit_children(node) @@ -63,32 +65,40 @@ class CreoleEmitter(BaseEmitter): def headline_emit(self, node): return "%s %s\n\n" % ("=" * node.level, self.emit_children(node)) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def strong_emit(self, node): return self._typeface(node, key="**") + b_emit = strong_emit big_emit = strong_emit def i_emit(self, node): return self._typeface(node, key="//") + em_emit = i_emit def tt_emit(self, node): return self._typeface(node, key="##") + def sup_emit(self, node): return self._typeface(node, key="^^") + def sub_emit(self, node): return self._typeface(node, key=",,") + def u_emit(self, node): return self._typeface(node, key="__") + def small_emit(self, node): return self._typeface(node, key="--") + def del_emit(self, node): return self._typeface(node, key="~~") + strike_emit = del_emit - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def hr_emit(self, node): return "----\n\n" @@ -101,26 +111,26 @@ class CreoleEmitter(BaseEmitter): # e.g.: <a name="anchor-one">foo</a> return link_text if link_text == url: - return "[[%s]]" % url + return f"[[{url}]]" else: - return "[[%s|%s]]" % (url, link_text) + return f"[[{url}|{link_text}]]" def img_emit(self, node): src = node.attrs["src"] - if src.split(':')[0] == 'data': + if src.split(":")[0] == "data": return "" title = node.attrs.get("title", "") alt = node.attrs.get("alt", "") width = node.attrs.get("height", None) height = node.attrs.get("width", None) - if len(alt) > len(title): # Use the longest one + if len(alt) > len(title): # Use the longest one text = alt else: text = title - if text == "": # Use filename as picture text + if text == "": # Use filename as picture text text = posixpath.basename(src) if not self.strict: @@ -129,7 +139,7 @@ class CreoleEmitter(BaseEmitter): return "{{%s|%s}}" % (src, text) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def ul_emit(self, node): return self._list_emit(node, list_type="*") @@ -137,7 +147,7 @@ class CreoleEmitter(BaseEmitter): def ol_emit(self, node): return self._list_emit(node, list_type="#") - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def div_emit(self, node): return self._emit_content(node) @@ -146,32 +156,24 @@ class CreoleEmitter(BaseEmitter): return self._emit_content(node) - - - - -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) -# import sys;sys.exit() + # import sys;sys.exit() from creole.parser.html_parser import HtmlParser data = """A <<unittest_macro1 args="foo1">>bar1<</unittest_macro1>> in a line...""" -# print(data.strip()) - h2c = HtmlParser( - debug=True - ) + # print(data.strip()) + h2c = HtmlParser(debug=True) document_tree = h2c.feed(data) h2c.debug() from creole.shared.unknown_tags import escape_unknown_nodes - e = CreoleEmitter(document_tree, - debug=True, - unknown_emit=escape_unknown_nodes - ) + e = CreoleEmitter(document_tree, debug=True, unknown_emit=escape_unknown_nodes) content = e.emit() print("*" * 79) print(content) diff --git a/creole/emitter/html2rest_emitter.py b/creole/emitter/html2rest_emitter.py index 7a32872..5c40e12 100644 --- a/creole/emitter/html2rest_emitter.py +++ b/creole/emitter/html2rest_emitter.py @@ -13,15 +13,18 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + + import posixpath from creole.shared.base_emitter import BaseEmitter from creole.shared.markup_table import MarkupTable - # Kink of nodes in which hyperlinks are stored in references intead of embedded urls. -DO_SUBSTITUTION = ("th", "td",) # TODO: In witch kind of node must we also substitude links? +DO_SUBSTITUTION = ( + "th", + "td", +) # TODO: In witch kind of node must we also substitude links? class Html2restException(Exception): @@ -33,6 +36,7 @@ class ReStructuredTextEmitter(BaseEmitter): Build from a document_tree (html2creole.parser.HtmlParser instance) a creole markup text. """ + def __init__(self, *args, **kwargs): super(ReStructuredTextEmitter, self).__init__(*args, **kwargs) @@ -55,23 +59,23 @@ class ReStructuredTextEmitter(BaseEmitter): self._substitution_data = [] return content - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def blockdata_pre_emit(self, node): """ pre block -> with newline at the end """ pre_block = self.deentity.replace_all(node.content).strip() pre_block = "\n".join([" %s" % line for line in pre_block.splitlines()]) - return "::\n\n%s\n\n" % pre_block + return f"::\n\n{pre_block}\n\n" def inlinedata_pre_emit(self, node): """ a pre inline block -> no newline at the end """ return "<pre>%s</pre>" % self.deentity.replace_all(node.content) def blockdata_pass_emit(self, node): - return "%s\n\n" % node.content + return f"{node.content}\n\n" return node.content - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def emit_children(self, node): """Emit all the children of a node.""" @@ -101,13 +105,14 @@ class ReStructuredTextEmitter(BaseEmitter): return "%s\n\n" % self.emit_children(node) HEADLINE_DATA = { - 1:("=", True), - 2:("-", True), - 3:("=", False), - 4:("-", False), - 5:('`', False), - 6:("'", False), + 1: ("=", True), + 2: ("-", True), + 3: ("=", False), + 4: ("-", False), + 5: ("`", False), + 6: ("'", False), } + def headline_emit(self, node): text = self.emit_children(node) @@ -123,21 +128,24 @@ class ReStructuredTextEmitter(BaseEmitter): else: format = "%(t)s\n%(m)s\n\n" - return format % {"m":markup, "t":text} + return format % {"m": markup, "t": text} - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _typeface(self, node, key): return key + self.emit_children(node) + key def strong_emit(self, node): return self._typeface(node, key="**") + def b_emit(self, node): return self._typeface(node, key="**") + big_emit = strong_emit def i_emit(self, node): return self._typeface(node, key="*") + def em_emit(self, node): return self._typeface(node, key="*") @@ -148,24 +156,24 @@ class ReStructuredTextEmitter(BaseEmitter): # FIXME: Is there no small in ReSt??? return self.emit_children(node) -# def sup_emit(self, node): -# return self._typeface(node, key="^") -# def sub_emit(self, node): -# return self._typeface(node, key="~") -# def del_emit(self, node): -# return self._typeface(node, key="-") -# -# def cite_emit(self, node): -# return self._typeface(node, key="??") -# def ins_emit(self, node): -# return self._typeface(node, key="+") -# -# def span_emit(self, node): -# return self._typeface(node, key="%") -# def code_emit(self, node): -# return self._typeface(node, key="@") - - #-------------------------------------------------------------------------- + # def sup_emit(self, node): + # return self._typeface(node, key="^") + # def sub_emit(self, node): + # return self._typeface(node, key="~") + # def del_emit(self, node): + # return self._typeface(node, key="-") + # + # def cite_emit(self, node): + # return self._typeface(node, key="??") + # def ins_emit(self, node): + # return self._typeface(node, key="+") + # + # def span_emit(self, node): + # return self._typeface(node, key="%") + # def code_emit(self, node): + # return self._typeface(node, key="@") + + # -------------------------------------------------------------------------- def hr_emit(self, node): return "----\n\n" @@ -209,56 +217,48 @@ class ReStructuredTextEmitter(BaseEmitter): # make a hyperlink reference if not old_url: # new substitution - self._substitution_data.append( - ".. _%s: %s" % (link_text, url) - ) - return "`%s`_" % link_text + self._substitution_data.append(f".. _{link_text}: {url}") + return f"`{link_text}`_" if old_url: # reuse a existing substitution - return "`%s`_" % link_text + return f"`{link_text}`_" else: # create a inline hyperlink - return "`%s <%s>`_" % (link_text, url) + return f"`{link_text} <{url}>`_" def img_emit(self, node): src = node.attrs["src"] - if src.split(':')[0] == 'data': + if src.split(":")[0] == "data": return "" title = node.attrs.get("title", "") alt = node.attrs.get("alt", "") - if len(alt) > len(title): # Use the longest one + if len(alt) > len(title): # Use the longest one substitution_text = alt else: substitution_text = title - if substitution_text == "": # Use filename as picture text + if substitution_text == "": # Use filename as picture text substitution_text = posixpath.basename(src) - old_src = self._get_old_substitution( - self._used_substitution_images, substitution_text, src - ) + old_src = self._get_old_substitution(self._used_substitution_images, substitution_text, src) if not old_src: - self._substitution_data.append( - ".. |%s| image:: %s" % (substitution_text, src) - ) + self._substitution_data.append(f".. |{substitution_text}| image:: {src}") - return "|%s|" % substitution_text + return f"|{substitution_text}|" - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def code_emit(self, node): return "``%s``" % self._emit_content(node) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def li_emit(self, node): content = self.emit_children(node).strip("\n") - result = "\n%s%s %s\n" % ( - " " * (node.level - 1), self._list_markup, content - ) + result = "\n%s%s %s\n" % (" " * (node.level - 1), self._list_markup, content) return result def _list_emit(self, node, list_type): @@ -268,7 +268,7 @@ class ReStructuredTextEmitter(BaseEmitter): if node.level == 1: # FIXME: This should be made easier and better complete_list = "\n\n".join([i.strip("\n") for i in content.split("\n") if i]) - content = "%s\n\n" % complete_list + content = f"{complete_list}\n\n" return content @@ -282,21 +282,18 @@ class ReStructuredTextEmitter(BaseEmitter): """ http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#tables """ - self._table = MarkupTable( - head_prefix="", - auto_width=True, - debug_msg=self.debug_msg - ) + self._table = MarkupTable(head_prefix="", auto_width=True, debug_msg=self.debug_msg) self.emit_children(node) content = self._table.get_rest_table() - return "%s\n\n" % content + return f"{content}\n\n" -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) -# import sys;sys.exit() + # import sys;sys.exit() from creole.parser.html_parser import HtmlParser data = """<p>A nested bullet lists:</p> @@ -326,17 +323,14 @@ if __name__ == '__main__': print(data) h2c = HtmlParser( -# debug=True + # debug=True ) document_tree = h2c.feed(data) h2c.debug() - e = ReStructuredTextEmitter(document_tree, - debug=True - ) + e = ReStructuredTextEmitter(document_tree, debug=True) content = e.emit() print("*" * 79) print(content) print("*" * 79) print(content.replace(" ", ".").replace("\n", "\\n\n")) - diff --git a/creole/emitter/html2textile_emitter.py b/creole/emitter/html2textile_emitter.py index 2263c12..ea04bbe 100644 --- a/creole/emitter/html2textile_emitter.py +++ b/creole/emitter/html2textile_emitter.py @@ -10,13 +10,13 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + + import posixpath from creole.shared.base_emitter import BaseEmitter - class TextileEmitter(BaseEmitter): """ Build from a document_tree (html2creole.parser.HtmlParser instance) a @@ -31,64 +31,71 @@ class TextileEmitter(BaseEmitter): def emit(self): """Emit the document represented by self.root DOM tree.""" - return self.emit_node(self.root).strip() # FIXME + return self.emit_node(self.root).strip() # FIXME - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def blockdata_pre_emit(self, node): """ pre block -> with newline at the end """ return "<pre>%s</pre>\n" % self.deentity.replace_all(node.content) + def inlinedata_pre_emit(self, node): """ a pre inline block -> no newline at the end """ return "<pre>%s</pre>" % self.deentity.replace_all(node.content) def blockdata_pass_emit(self, node): - return "%s\n\n" % node.content + return f"{node.content}\n\n" return node.content - - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def p_emit(self, node): return "%s\n\n" % self.emit_children(node) def headline_emit(self, node): - return "h%i. %s\n\n" % (node.level, self.emit_children(node)) + return f"h{node.level:d}. {self.emit_children(node)}\n\n" - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _typeface(self, node, key): return key + self.emit_children(node) + key def strong_emit(self, node): return self._typeface(node, key="*") + def b_emit(self, node): return self._typeface(node, key="**") + big_emit = strong_emit def i_emit(self, node): return self._typeface(node, key="__") + def em_emit(self, node): return self._typeface(node, key="_") def sup_emit(self, node): return self._typeface(node, key="^") + def sub_emit(self, node): return self._typeface(node, key="~") + def del_emit(self, node): return self._typeface(node, key="-") def cite_emit(self, node): return self._typeface(node, key="??") + def ins_emit(self, node): return self._typeface(node, key="+") def span_emit(self, node): return self._typeface(node, key="%") + def code_emit(self, node): return self._typeface(node, key="@") - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def hr_emit(self, node): return "----\n\n" @@ -96,27 +103,27 @@ class TextileEmitter(BaseEmitter): def a_emit(self, node): link_text = self.emit_children(node) url = node.attrs["href"] - return '"%s":%s' % (link_text, url) + return f'"{link_text}":{url}' def img_emit(self, node): src = node.attrs["src"] - if src.split(':')[0] == 'data': + if src.split(":")[0] == "data": return "" title = node.attrs.get("title", "") alt = node.attrs.get("alt", "") - if len(alt) > len(title): # Use the longest one + if len(alt) > len(title): # Use the longest one text = alt else: text = title - if text == "": # Use filename as picture text + if text == "": # Use filename as picture text text = posixpath.basename(src) - return "!%s(%s)!" % (src, text) + return f"!{src}({text})!" - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def ul_emit(self, node): return self._list_emit(node, list_type="*") @@ -125,17 +132,12 @@ class TextileEmitter(BaseEmitter): return self._list_emit(node, list_type="#") - - - - - - -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) -# import sys;sys.exit() + # import sys;sys.exit() from creole.parser.html_parser import HtmlParser data = """ @@ -152,16 +154,12 @@ if __name__ == '__main__': </table> """ -# print(data.strip()) - h2c = HtmlParser( - debug=True - ) + # print(data.strip()) + h2c = HtmlParser(debug=True) document_tree = h2c.feed(data) h2c.debug() - e = TextileEmitter(document_tree, - debug=True - ) + e = TextileEmitter(document_tree, debug=True) content = e.emit() print("*" * 79) print(content) diff --git a/creole/exceptions.py b/creole/exceptions.py index 44cddff..721d50f 100644 --- a/creole/exceptions.py +++ b/creole/exceptions.py @@ -4,12 +4,13 @@ """ python-creole exceptions ~~~~~~~~~~~~~~~~~~~~~~~~ - + :copyleft: 2011 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + + class DocutilsImportError(ImportError): pass diff --git a/creole/html_tools/deentity.py b/creole/html_tools/deentity.py index 7a6ff1a..32c1e1b 100644 --- a/creole/html_tools/deentity.py +++ b/creole/html_tools/deentity.py @@ -3,33 +3,25 @@ """ python-creole utils - ~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~ :copyleft: 2008-2011 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re -try: - import htmlentitydefs as entities -except ImportError: - from html import entities # python 3 -from creole.py3compat import PY3 -entities_rules = '|'.join([ - r"(&\#(?P<number>\d+);)", - r"(&\#x(?P<hex>[a-fA-F0-9]+);)", - r"(&(?P<named>[a-zA-Z]+);)", -]) -#print(entities_rules) -entities_regex = re.compile( - entities_rules, re.VERBOSE | re.UNICODE | re.MULTILINE -) +from html import entities + + +entities_rules = "|".join([r"(&\#(?P<number>\d+);)", r"(&\#x(?P<hex>[a-fA-F0-9]+);)", r"(&(?P<named>[a-zA-Z]+);)",]) +# print(entities_rules) +entities_regex = re.compile(entities_rules, re.VERBOSE | re.UNICODE | re.MULTILINE) class Deentity(object): @@ -39,7 +31,7 @@ class Deentity(object): >>> d = Deentity() >>> d.replace_all("-=[ >>>nice<<< ]=-") '-=[ >>>nice<<< ]=-' - + >>> d.replace_all("-=[Mühlheim]=-") # uuml - latin small letter u with diaeresis '-=[M\\xfchlheim]=-' @@ -50,21 +42,16 @@ class Deentity(object): >>> d.replace_named("amp") '&' """ + def replace_number(self, text): """ unicode number entity """ unicode_no = int(text) - if PY3: - return chr(unicode_no) - else: - return unichr(unicode_no) + return chr(unicode_no) def replace_hex(self, text): """ hex entity """ unicode_no = int(text, 16) - if PY3: - return chr(unicode_no) - else: - return unichr(unicode_no) + return chr(unicode_no) def replace_named(self, text): """ named entity """ @@ -73,18 +60,16 @@ class Deentity(object): return " " else: codepoint = entities.name2codepoint[text] - if PY3: - return chr(codepoint) - else: - return unichr(codepoint) + return chr(codepoint) def replace_all(self, content): """ replace all html entities form the given text. """ + def replace_entity(match): groups = match.groupdict() for name, text in groups.items(): if text is not None: - replace_method = getattr(self, 'replace_%s' % name) + replace_method = getattr(self, f"replace_{name}") return replace_method(text) # Should never happen: @@ -93,6 +78,7 @@ class Deentity(object): return entities_regex.sub(replace_entity, content) -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/html_tools/strip_html.py b/creole/html_tools/strip_html.py index 20b6788..0e00407 100644 --- a/creole/html_tools/strip_html.py +++ b/creole/html_tools/strip_html.py @@ -4,20 +4,19 @@ """ python-creole utils - ~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~ :copyleft: 2008-2011 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re from creole.parser.html_parser_config import BLOCK_TAGS - strip_html_regex = re.compile( r""" \s* @@ -29,11 +28,10 @@ strip_html_regex = re.compile( > \s* """, - re.VERBOSE | re.MULTILINE | re.UNICODE + re.VERBOSE | re.MULTILINE | re.UNICODE, ) - def strip_html(html_code): """ Delete whitespace from html code. Doesn't recordnize preformatted blocks! @@ -68,12 +66,12 @@ def strip_html(html_code): startend_tag = match.group("startend") in ("/", "/") tag = match.group("tag") -# print("_"*40) -# print(match.groupdict()) -# print("block.......: %r" % block) -# print("end_tag.....:", end_tag) -# print("startend_tag:", startend_tag) -# print("tag.........: %r" % tag) + # print("_"*40) + # print(match.groupdict()) + # print("block.......: %r" % block) + # print("end_tag.....:", end_tag) + # print("startend_tag:", startend_tag) + # print("tag.........: %r" % tag) if tag in BLOCK_TAGS: return block.strip() @@ -90,10 +88,10 @@ def strip_html(html_code): elif startend_tag: # It's a closed start tag e.g.: <br /> - if space_start: # there was space before the tag + if space_start: # there was space before the tag result = " " + result - if space_end: # there was space after the tag + if space_end: # there was space after the tag result += " " else: # a start tag e.g.: <strong> @@ -108,6 +106,7 @@ def strip_html(html_code): return clean_data -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/html_tools/text_tools.py b/creole/html_tools/text_tools.py index 28be3c9..fb49804 100644 --- a/creole/html_tools/text_tools.py +++ b/creole/html_tools/text_tools.py @@ -4,19 +4,20 @@ """ python-creole utils - ~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~ :copyleft: 2008-2011 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import re +import re space_re = re.compile(r"^(\s*)(.*?)(\s*)$", re.DOTALL) + + def clean_whitespace(txt): """ Special whitespaces cleanup @@ -33,6 +34,7 @@ def clean_whitespace(txt): >>> clean_whitespace("foo bar") 'foo bar' """ + def cleanup(match): start, txt, end = match.groups() @@ -51,6 +53,7 @@ def clean_whitespace(txt): return space_re.sub(cleanup, txt) -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/parser/creol2html_parser.py b/creole/parser/creol2html_parser.py index ab09a35..c326c3b 100644 --- a/creole/parser/creol2html_parser.py +++ b/creole/parser/creol2html_parser.py @@ -22,13 +22,12 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re -from creole.parser.creol2html_rules import BlockRules, INLINE_FLAGS, INLINE_RULES, \ - SpecialRules, InlineRules -from creole.py3compat import TEXT_TYPE +from creole.parser.creol2html_rules import INLINE_FLAGS, INLINE_RULES, BlockRules, InlineRules, SpecialRules + from creole.shared.document_tree import DocNode @@ -37,49 +36,44 @@ class CreoleParser(object): Parse the raw text and create a document object that can be converted into output using Emitter. """ + # For pre escaping, in creole 1.0 done with ~: - pre_escape_re = re.compile( - SpecialRules.pre_escape, re.MULTILINE | re.VERBOSE | re.UNICODE - ) + pre_escape_re = re.compile(SpecialRules.pre_escape, re.MULTILINE | re.VERBOSE | re.UNICODE) # for link descriptions: link_re = re.compile( - '|'.join([InlineRules.image, InlineRules.linebreak, InlineRules.char]), - re.VERBOSE | re.UNICODE + "|".join([InlineRules.image, InlineRules.linebreak, InlineRules.char]), re.VERBOSE | re.UNICODE ) # for list items: - item_re = re.compile( - SpecialRules.item, re.VERBOSE | re.UNICODE | re.MULTILINE - ) + item_re = re.compile(SpecialRules.item, re.VERBOSE | re.UNICODE | re.MULTILINE) # for table cells: cell_re = re.compile(SpecialRules.cell, re.VERBOSE | re.UNICODE) # For inline elements: - inline_re = re.compile('|'.join(INLINE_RULES), INLINE_FLAGS) - + inline_re = re.compile("|".join(INLINE_RULES), INLINE_FLAGS) def __init__(self, raw, block_rules=None, blog_line_breaks=True): - assert isinstance(raw, TEXT_TYPE) + assert isinstance(raw, str) self.raw = raw if block_rules is None: block_rules = BlockRules(blog_line_breaks=blog_line_breaks) # setup block element rules: - self.block_re = re.compile('|'.join(block_rules.rules), block_rules.re_flags) + self.block_re = re.compile("|".join(block_rules.rules), block_rules.re_flags) self.blog_line_breaks = blog_line_breaks - self.root = DocNode('document', None) - self.cur = self.root # The most recent document node - self.text = None # The node to add inline characters to - self.last_text_break = None # Last break node, inserted by _text_repl() + self.root = DocNode("document", None) + self.cur = self.root # The most recent document node + self.text = None # The node to add inline characters to + self.last_text_break = None # Last break node, inserted by _text_repl() # Filled with all macros that's in the text self.root.used_macros = set() - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def cleanup_break(self, old_cur): """ @@ -93,7 +87,7 @@ class CreoleParser(object): if self.cur.children: last_child = self.cur.children[-1] if last_child.kind == "break": - del(self.cur.children[-1]) + del self.cur.children[-1] def _upto(self, node, kinds): """ @@ -101,85 +95,87 @@ class CreoleParser(object): of one of the listed kinds of nodes or root. Start at the node node. """ - self.cleanup_break(node) # remove unused end line breaks. + self.cleanup_break(node) # remove unused end line breaks. while node.parent is not None and not node.kind in kinds: node = node.parent return node def _upto_block(self): - self.cur = self._upto(self.cur, ('document',))# 'section', 'blockquote')) + self.cur = self._upto(self.cur, ("document",)) # 'section', 'blockquote')) - #__________________________________________________________________________ + # __________________________________________________________________________ # The _*_repl methods called for matches in regexps. Sometimes the # same method needs several names, because of group names in regexps. def _text_repl(self, groups): -# print("_text_repl()", self.cur.kind) -# self.debug_groups(groups) + # print("_text_repl()", self.cur.kind) + # self.debug_groups(groups) - if self.cur.kind in ('table', 'table_row', 'bullet_list', 'number_list'): + if self.cur.kind in ("table", "table_row", "bullet_list", "number_list"): self._upto_block() - if self.cur.kind in ('document', 'section', 'blockquote'): - self.cur = DocNode('paragraph', self.cur) + if self.cur.kind in ("document", "section", "blockquote"): + self.cur = DocNode("paragraph", self.cur) - text = groups.get('text', "") + text = groups.get("text", "") - if groups.get('space'): + if groups.get("space"): # use wikipedia style line breaks and seperate a new line with one space text = " " + text self.parse_inline(text) - if groups.get('break') and self.cur.kind in ('paragraph', - 'emphasis', 'strong', 'pre_inline'): - self.last_text_break = DocNode('break', self.cur, "") + if groups.get("break") and self.cur.kind in ("paragraph", "emphasis", "strong", "pre_inline"): + self.last_text_break = DocNode("break", self.cur, "") self.text = None + _break_repl = _text_repl _space_repl = _text_repl def _url_repl(self, groups): """Handle raw urls in text.""" - if not groups.get('escaped_url'): + if not groups.get("escaped_url"): # this url is NOT escaped - target = groups.get('url_target', "") - node = DocNode('link', self.cur) + target = groups.get("url_target", "") + node = DocNode("link", self.cur) node.content = target - DocNode('text', node, node.content) + DocNode("text", node, node.content) self.text = None else: # this url is escaped, we render it as text if self.text is None: - self.text = DocNode('text', self.cur, "") - self.text.content += groups.get('url_target') + self.text = DocNode("text", self.cur, "") + self.text.content += groups.get("url_target") + _url_target_repl = _url_repl _url_proto_repl = _url_repl _escaped_url_repl = _url_repl def _link_repl(self, groups): """Handle all kinds of links.""" - target = groups.get('link_target', "") - text = (groups.get('link_text', "") or "").strip() + target = groups.get("link_target", "") + text = (groups.get("link_text", "") or "").strip() parent = self.cur - self.cur = DocNode('link', self.cur) + self.cur = DocNode("link", self.cur) self.cur.content = target self.text = None re.sub(self.link_re, self._replace, text) self.cur = parent self.text = None + _link_target_repl = _link_repl _link_text_repl = _link_repl - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _add_macro(self, groups, macro_type, name_key, args_key, text_key=None): """ generic method to handle the macro, used for all variants: inline, inline-tag, block """ - #self.debug_groups(groups) + # self.debug_groups(groups) assert macro_type in ("macro_inline", "macro_block") if text_key: @@ -212,6 +208,7 @@ class CreoleParser(object): args_key="macro_block_args", text_key="macro_block_text", ) + _macro_block_start_repl = _macro_block_repl _macro_block_args_repl = _macro_block_repl _macro_block_text_repl = _macro_block_repl @@ -221,16 +218,12 @@ class CreoleParser(object): A single macro tag, e.g.: <<macro-a foo="bar">> or <<macro />> """ self._add_macro( - groups, - macro_type="macro_inline", - name_key="macro_tag_name", - args_key="macro_tag_args", - text_key=None, + groups, macro_type="macro_inline", name_key="macro_tag_name", args_key="macro_tag_args", text_key=None, ) + _macro_tag_name_repl = _macro_tag_repl _macro_tag_args_repl = _macro_tag_repl - def _macro_inline_repl(self, groups): """ inline macro tag with data, e.g.: <<macro>>text<</macro>> @@ -242,54 +235,57 @@ class CreoleParser(object): args_key="macro_inline_args", text_key="macro_inline_text", ) + _macro_inline_start_repl = _macro_inline_repl _macro_inline_args_repl = _macro_inline_repl _macro_inline_text_repl = _macro_inline_repl - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _image_repl(self, groups): """Handles images and attachemnts included in the page.""" - target = groups.get('image_target', "").strip() - text = (groups.get('image_text', "") or "").strip() + target = groups.get("image_target", "").strip() + text = (groups.get("image_text", "") or "").strip() node = DocNode("image", self.cur, target) - DocNode('text', node, text or node.content) + DocNode("text", node, text or node.content) self.text = None + _image_target_repl = _image_repl _image_text_repl = _image_repl def _separator_repl(self, groups): self._upto_block() - DocNode('separator', self.cur) + DocNode("separator", self.cur) def _item_repl(self, groups): """ List item """ - bullet = groups.get('item_head', "") - text = groups.get('item_text', "") - if bullet[-1] == '#': - kind = 'number_list' + bullet = groups.get("item_head", "") + text = groups.get("item_text", "") + if bullet[-1] == "#": + kind = "number_list" else: - kind = 'bullet_list' + kind = "bullet_list" level = len(bullet) - 1 lst = self.cur # Find a list of the same kind and level up the tree - while (lst and - not (lst.kind in ('number_list', 'bullet_list') and - lst.level == level) and - not lst.kind in ('document', 'section', 'blockquote')): + while ( + lst + and not (lst.kind in ("number_list", "bullet_list") and lst.level == level) + and not lst.kind in ("document", "section", "blockquote") + ): lst = lst.parent if lst and lst.kind == kind: self.cur = lst else: # Create a new level of list - self.cur = self._upto(self.cur, - ('list_item', 'document', 'section', 'blockquote')) + self.cur = self._upto(self.cur, ("list_item", "document", "section", "blockquote")) self.cur = DocNode(kind, self.cur) self.cur.level = level - self.cur = DocNode('list_item', self.cur) + self.cur = DocNode("list_item", self.cur) self.cur.level = level + 1 self.parse_inline(text) self.text = None + _item_text_repl = _item_repl _item_head_repl = _item_repl @@ -299,31 +295,31 @@ class CreoleParser(object): def _head_repl(self, groups): self._upto_block() - node = DocNode('header', self.cur, groups['head_text'].strip()) - node.level = len(groups['head_head']) + node = DocNode("header", self.cur, groups["head_text"].strip()) + node.level = len(groups["head_head"]) self.text = None + _head_head_repl = _head_repl _head_text_repl = _head_repl def _table_repl(self, groups): - row = groups.get('table', '|').strip() - self.cur = self._upto(self.cur, ( - 'table', 'document', 'section', 'blockquote')) - if self.cur.kind != 'table': - self.cur = DocNode('table', self.cur) + row = groups.get("table", "|").strip() + self.cur = self._upto(self.cur, ("table", "document", "section", "blockquote")) + if self.cur.kind != "table": + self.cur = DocNode("table", self.cur) tb = self.cur - tr = DocNode('table_row', tb) + tr = DocNode("table_row", tb) for m in self.cell_re.finditer(row): - cell = m.group('cell') + cell = m.group("cell") if cell: text = cell.strip() - self.cur = DocNode('table_cell', tr) + self.cur = DocNode("table_cell", tr) self.text = None else: - text = m.group('head').strip('= ') - self.cur = DocNode('table_head', tr) - self.text = DocNode('text', self.cur, "") + text = m.group("head").strip("= ") + self.cur = DocNode("table_head", tr) + self.text = DocNode("text", self.cur, "") self.parse_inline(text) self.cur = tb @@ -331,14 +327,17 @@ class CreoleParser(object): def _pre_block_repl(self, groups): self._upto_block() - kind = groups.get('pre_block_kind', None) - text = groups.get('pre_block_text', "") + kind = groups.get("pre_block_kind", None) + text = groups.get("pre_block_text", "") + def remove_tilde(m): - return m.group('indent') + m.group('rest') + return m.group("indent") + m.group("rest") + text = self.pre_escape_re.sub(remove_tilde, text) - node = DocNode('pre_block', self.cur, text) - node.sect = kind or '' + node = DocNode("pre_block", self.cur, text) + node.sect = kind or "" self.text = None + _pre_block_text_repl = _pre_block_repl _pre_block_head_repl = _pre_block_repl _pre_block_kind_repl = _pre_block_repl @@ -346,95 +345,104 @@ class CreoleParser(object): def _line_repl(self, groups): """ Transfer newline from the original markup into the html code """ self._upto_block() - DocNode('line', self.cur, "") + DocNode("line", self.cur, "") def _pre_inline_repl(self, groups): - text = groups.get('pre_inline_text', "") - DocNode('pre_inline', self.cur, text) + text = groups.get("pre_inline_text", "") + DocNode("pre_inline", self.cur, text) self.text = None + _pre_inline_text_repl = _pre_inline_repl _pre_inline_head_repl = _pre_inline_repl - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _inline_mark(self, groups, key): self.cur = DocNode(key, self.cur) self.text = None - text = groups["%s_text" % key] + text = groups[f"{key}_text"] self.parse_inline(text) self.cur = self._upto(self.cur, (key,)).parent self.text = None - # TODO: How can we generalize that: def _emphasis_repl(self, groups): - self._inline_mark(groups, key='emphasis') + self._inline_mark(groups, key="emphasis") + _emphasis_text_repl = _emphasis_repl def _strong_repl(self, groups): - self._inline_mark(groups, key='strong') + self._inline_mark(groups, key="strong") + _strong_text_repl = _strong_repl def _monospace_repl(self, groups): - self._inline_mark(groups, key='monospace') + self._inline_mark(groups, key="monospace") + _monospace_text_repl = _monospace_repl def _superscript_repl(self, groups): - self._inline_mark(groups, key='superscript') + self._inline_mark(groups, key="superscript") + _superscript_text_repl = _superscript_repl def _subscript_repl(self, groups): - self._inline_mark(groups, key='subscript') + self._inline_mark(groups, key="subscript") + _subscript_text_repl = _subscript_repl def _underline_repl(self, groups): - self._inline_mark(groups, key='underline') + self._inline_mark(groups, key="underline") + _underline_text_repl = _underline_repl def _small_repl(self, groups): - self._inline_mark(groups, key='small') + self._inline_mark(groups, key="small") + _small_text_repl = _small_repl def _delete_repl(self, groups): - self._inline_mark(groups, key='delete') + self._inline_mark(groups, key="delete") + _delete_text_repl = _delete_repl - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _linebreak_repl(self, groups): - DocNode('break', self.cur, None) + DocNode("break", self.cur, None) self.text = None def _escape_repl(self, groups): if self.text is None: - self.text = DocNode('text', self.cur, "") - self.text.content += groups.get('escaped_char', "") + self.text = DocNode("text", self.cur, "") + self.text.content += groups.get("escaped_char", "") + _escaped_char_repl = _escape_repl def _char_repl(self, groups): if self.text is None: - self.text = DocNode('text', self.cur, "") - self.text.content += groups.get('char', "") + self.text = DocNode("text", self.cur, "") + self.text.content += groups.get("char", "") - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _replace(self, match): """Invoke appropriate _*_repl method. Called for every matched group.""" -# def debug(groups): -# from pprint import pformat -# data = dict([ -# group for group in groups.items() if group[1] is not None -# ]) -# print("%s\n" % pformat(data)) + # def debug(groups): + # from pprint import pformat + # data = dict([ + # group for group in groups.items() if group[1] is not None + # ]) + # print("%s\n" % pformat(data)) groups = match.groupdict() for name, text in groups.items(): if text is not None: - #if name != "char": debug(groups) - replace_method = getattr(self, '_%s_repl' % name) + # if name != "char": debug(groups) + replace_method = getattr(self, f"_{name}_repl") replace_method(groups) return @@ -453,8 +461,7 @@ class CreoleParser(object): self.parse_block(text) return self.root - - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def debug(self, start_node=None): """ Display the current document tree @@ -465,13 +472,15 @@ class CreoleParser(object): start_node = self.root print(" document tree:") else: - print(" tree from %s:" % start_node) + print(f" tree from {start_node}:") print("=" * 80) + def emit(node, ident=0): for child in node.children: print("%s%s: %r" % (" " * ident, child.kind, child.content)) emit(child, ident + 4) + emit(start_node) print("*" * 80) @@ -484,11 +493,9 @@ class CreoleParser(object): print("-" * 80) - - - if __name__ == "__main__": import doctest + print(doctest.testmod()) print("-" * 80) @@ -510,7 +517,6 @@ if __name__ == "__main__": if name != "char" and text != None: print("%20s: %r" % (name, text)) - parser = CreoleParser("", blog_line_breaks=blog_line_breaks) print("_" * 80) @@ -521,7 +527,6 @@ if __name__ == "__main__": print("merged inline rules test:") re.sub(parser.inline_re, display_match, txt) - def test_single(rules, flags, txt): for rule in rules: rexp = re.compile(rule, flags) @@ -536,5 +541,4 @@ if __name__ == "__main__": print("single inline rules match test:") test_single(INLINE_RULES, INLINE_FLAGS, txt) - print("---END---") diff --git a/creole/parser/creol2html_rules.py b/creole/parser/creol2html_rules.py index 01bb08e..b507757 100644 --- a/creole/parser/creol2html_rules.py +++ b/creole/parser/creol2html_rules.py @@ -9,7 +9,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re @@ -18,217 +18,223 @@ class InlineRules(object): """ All inline rules """ - proto = r'http|https|ftp|nntp|news|mailto|telnet|file|irc' + + proto = r"http|https|ftp|nntp|news|mailto|telnet|file|irc" # New regex for finding uris, requires uri to free stand within whitespace or lineends. - url = r'''(?P<url> + url = ( + r"""(?P<url> (^ | (?<=\s)) (?P<escaped_url>~)? (?P<url_target> (?P<url_proto> %s )://[^$\s]+ ) - )''' % proto + )""" + % proto + ) # Original uri matching regex inherited from MoinMoin code. - #url = r'''(?P<url> - #(^ | (?<=\s | [.,:;!?()/=])) - #(?P<escaped_url>~)? - #(?P<url_target> (?P<url_proto> %s ):\S+? ) - #($ | (?=\s | [,.:;!?()] (\s | $))) - #)''' % proto - link = r'''(?P<link> + # url = r'''(?P<url> + # (^ | (?<=\s | [.,:;!?()/=])) + # (?P<escaped_url>~)? + # (?P<url_target> (?P<url_proto> %s ):\S+? ) + # ($ | (?=\s | [,.:;!?()] (\s | $))) + # )''' % proto + link = r"""(?P<link> \[\[ (?P<link_target>.+?) \s* ([|] \s* (?P<link_text>.+?) \s*)? ]] - )''' - -# link = r'''(?P<link1> -# \[\[ -# (?P<link_target1>.+?)\|(?P<link_text1>.+?) -# ]] -# )|(?P<link2> -# \[\[ -# (?P<link_target2> (%s)://[^ ]+) \s* (?P<link_text2>.+?) -# ]] -# )| -# \[\[(?P<internal_link>.+)\]\] -# ''' % proto + )""" + + # link = r'''(?P<link1> + # \[\[ + # (?P<link_target1>.+?)\|(?P<link_text1>.+?) + # ]] + # )|(?P<link2> + # \[\[ + # (?P<link_target2> (%s)://[^ ]+) \s* (?P<link_text2>.+?) + # ]] + # )| + # \[\[(?P<internal_link>.+)\]\] + # ''' % proto # image tag - image = r'''(?P<image> + image = r"""(?P<image> {{ (?P<image_target>.+?) \s* (\| \s* (?P<image_text>.+?) \s*)? }} - )(?i)''' - #-------------------------------------------------------------------------- + )(?i)""" + # -------------------------------------------------------------------------- # a macro like: <<macro>>text<</macro>> - macro_inline = r''' + macro_inline = r""" (?P<macro_inline> << \s* (?P<macro_inline_start>\w+) \s* (?P<macro_inline_args>.*?) \s* >> (?P<macro_inline_text>(.|\n)*?) <</ \s* (?P=macro_inline_start) \s* >> ) - ''' + """ # A single macro tag, like <<macro-a foo="bar">> or <<macro />> - macro_tag = r'''(?P<macro_tag> + macro_tag = r"""(?P<macro_tag> <<(?P<macro_tag_name> \w+) (?P<macro_tag_args>.*?) \s* /*>> - )''' + )""" - pre_inline = r'(?P<pre_inline> {{{ (?P<pre_inline_text>.*?) }}} )' + pre_inline = r"(?P<pre_inline> {{{ (?P<pre_inline_text>.*?) }}} )" # Basic text typefaces: - emphasis = r'(?P<emphasis>(?<!:)// (?P<emphasis_text>.+?) (?<!:)// )' + emphasis = r"(?P<emphasis>(?<!:)// (?P<emphasis_text>.+?) (?<!:)// )" # there must be no : in front of the // avoids italic rendering # in urls with unknown protocols - strong = r'(?P<strong>\*\* (?P<strong_text>.+?) \*\* )' + strong = r"(?P<strong>\*\* (?P<strong_text>.+?) \*\* )" # Creole 1.0 optional: - monospace = r'(?P<monospace> \#\# (?P<monospace_text>.+?) \#\# )' - superscript = r'(?P<superscript> \^\^ (?P<superscript_text>.+?) \^\^ )' - subscript = r'(?P<subscript> ,, (?P<subscript_text>.+?) ,, )' - underline = r'(?P<underline> __ (?P<underline_text>.+?) __ )' - delete = r'(?P<delete> ~~ (?P<delete_text>.+?) ~~ )' + monospace = r"(?P<monospace> \#\# (?P<monospace_text>.+?) \#\# )" + superscript = r"(?P<superscript> \^\^ (?P<superscript_text>.+?) \^\^ )" + subscript = r"(?P<subscript> ,, (?P<subscript_text>.+?) ,, )" + underline = r"(?P<underline> __ (?P<underline_text>.+?) __ )" + delete = r"(?P<delete> ~~ (?P<delete_text>.+?) ~~ )" # own additions: - small = r'(?P<small>-- (?P<small_text>.+?) -- )' - - linebreak = r'(?P<linebreak> \\\\ )' - escape = r'(?P<escape> ~ (?P<escaped_char>\S) )' - char = r'(?P<char> . )' - - - + small = r"(?P<small>-- (?P<small_text>.+?) -- )" + linebreak = r"(?P<linebreak> \\\\ )" + escape = r"(?P<escape> ~ (?P<escaped_char>\S) )" + char = r"(?P<char> . )" class BlockRules(object): """ All used block rules. """ -# macro_block = r'''(?P<macro_block> -# \s* << (?P<macro_block_start>\w+) \s* (?P<macro_block_args>.*?) >> -# (?P<macro_block_text>(.|\n)+?) -# <</(?P=macro_block_start)>> \s* -# )''' -# macro_block = r'''(?P<macro_block> -# <<(?P<macro_block_start>.*?)>> -# (?P<macro_block_text>.*?) -# <</.*?>> -# )''' - - macro_block = r''' + + # macro_block = r'''(?P<macro_block> + # \s* << (?P<macro_block_start>\w+) \s* (?P<macro_block_args>.*?) >> + # (?P<macro_block_text>(.|\n)+?) + # <</(?P=macro_block_start)>> \s* + # )''' + # macro_block = r'''(?P<macro_block> + # <<(?P<macro_block_start>.*?)>> + # (?P<macro_block_text>.*?) + # <</.*?>> + # )''' + + macro_block = r""" (?P<macro_block> << \s* (?P<macro_block_start>\w+) \s* (?P<macro_block_args>.*?) \s* >> (?P<macro_block_text>(.|\n)*?) <</ \s* (?P=macro_block_start) \s* >> ) - ''' + """ - line = r'''(?P<line> ^\s*$ )''' # empty line that separates paragraphs + line = r"""(?P<line> ^\s*$ )""" # empty line that separates paragraphs - head = r'''(?P<head> + head = r"""(?P<head> ^ (?P<head_head>=+) \s* (?P<head_text> .*? ) (=|\s)*?$ - )''' - separator = r'(?P<separator> ^ \s* ---- \s* $ )' # horizontal line + )""" + separator = r"(?P<separator> ^ \s* ---- \s* $ )" # horizontal line - pre_block = r'''(?P<pre_block> + pre_block = r"""(?P<pre_block> ^{{{ \s* $ (?P<pre_block_text> ([\#]!(?P<pre_block_kind>\w*?)(\s+.*)?$)? (.|\n)+? ) ^}}}) - ''' + """ # Matches the whole list, separate items are parsed later. The # list *must* start with a single bullet. - list = r'''(?P<list> + list = r"""(?P<list> ^ [ \t]* ([*][^*\#]|[\#][^\#*]).* $ ( \n[ \t]* [*\#]+.* $ )* - )''' + )""" - table = r'''^ \s*(?P<table> + table = r"""^ \s*(?P<table> [|].*? \s* [|]? - ) \s* $''' + ) \s* $""" re_flags = re.VERBOSE | re.UNICODE | re.MULTILINE def __init__(self, blog_line_breaks=True): if blog_line_breaks: - # use blog style line breaks (every line break would be converted into <br />) - self.text = r'(?P<text> .+ ) (?P<break> (?<!\\)$\n(?!\s*$) )?' + # use blog style line breaks (every line break would be converted into <br />) + self.text = r"(?P<text> .+ ) (?P<break> (?<!\\)$\n(?!\s*$) )?" else: # use wiki style line breaks, seperate lines with one space - self.text = r'(?P<space> (?<!\\)$\n(?!\s*$) )? (?P<text> .+ )' + self.text = r"(?P<space> (?<!\\)$\n(?!\s*$) )? (?P<text> .+ )" self.rules = ( self.macro_block, - self.line, self.head, self.separator, - self.pre_block, self.list, - self.table, self.text, + self.line, + self.head, + self.separator, + self.pre_block, + self.list, + self.table, + self.text, ) - - - class SpecialRules(object): """ re rules witch not directly used as inline/block rules. """ + # Matches single list items: - item = r'''^ \s* (?P<item> + item = r"""^ \s* (?P<item> (?P<item_head> [\#*]+) \s* (?P<item_text> .*?) - ) \s* $''' + ) \s* $""" # For splitting table cells: - cell = r''' + cell = r""" \| \s* ( (?P<head> [=][^|]+ ) | (?P<cell> ( %s | [^|])+ ) ) \s* - ''' % '|'.join([ - InlineRules.link, - InlineRules.macro_inline, InlineRules.macro_tag, - InlineRules.image, - InlineRules.pre_inline - ]) + """ % "|".join( + [InlineRules.link, InlineRules.macro_inline, InlineRules.macro_tag, InlineRules.image, InlineRules.pre_inline] + ) # For pre escaping, in creole 1.0 done with ~: - pre_escape = r' ^(?P<indent>\s*) ~ (?P<rest> \}\}\} \s*) $' + pre_escape = r" ^(?P<indent>\s*) ~ (?P<rest> \}\}\} \s*) $" INLINE_FLAGS = re.VERBOSE | re.UNICODE INLINE_RULES = ( - InlineRules.link, InlineRules.url, - InlineRules.macro_inline, InlineRules.macro_tag, - InlineRules.pre_inline, InlineRules.image, - - InlineRules.strong, InlineRules.emphasis, - InlineRules.monospace, InlineRules.underline, - InlineRules.superscript, InlineRules.subscript, - InlineRules.small, InlineRules.delete, - + InlineRules.link, + InlineRules.url, + InlineRules.macro_inline, + InlineRules.macro_tag, + InlineRules.pre_inline, + InlineRules.image, + InlineRules.strong, + InlineRules.emphasis, + InlineRules.monospace, + InlineRules.underline, + InlineRules.superscript, + InlineRules.subscript, + InlineRules.small, + InlineRules.delete, InlineRules.linebreak, - InlineRules.escape, InlineRules.char + InlineRules.escape, + InlineRules.char, ) def _verify_rules(rules, flags): """ Simple verify the rules -> try to compile it ;) - + >>> _verify_rules(INLINE_RULES, INLINE_FLAGS) Rule test ok. - - >>> block_rules = BlockRules() + + >>> block_rules = BlockRules() >>> _verify_rules(block_rules.rules, block_rules.re_flags) Rule test ok. """ @@ -236,12 +242,12 @@ def _verify_rules(rules, flags): rule_list = [] for rule in rules: try: -# print(rule) + # print(rule) re.compile(rule, flags) # Try to merge the rules. e.g. Check if group named double used. rule_list.append(rule) - re.compile('|'.join(rule_list), flags) + re.compile("|".join(rule_list), flags) except Exception as err: print(" *** Error with rule:") print(rule) @@ -252,6 +258,7 @@ def _verify_rules(rules, flags): if __name__ == "__main__": import doctest + print(doctest.testmod()) print("-" * 80) diff --git a/creole/parser/html_parser.py b/creole/parser/html_parser.py index fa60091..238bf2d 100644 --- a/creole/parser/html_parser.py +++ b/creole/parser/html_parser.py @@ -10,47 +10,51 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re import warnings -from creole.parser.html_parser_config import BLOCK_TAGS, IGNORE_TAGS from creole.html_tools.strip_html import strip_html -from creole.py3compat import TEXT_TYPE, BINARY_TYPE -from creole.shared.document_tree import DocNode, DebugList +from creole.parser.html_parser_config import BLOCK_TAGS, IGNORE_TAGS +from creole.shared.document_tree import DebugList, DocNode from creole.shared.html_parser import HTMLParser +# ------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -block_re = re.compile(r''' +block_re = re.compile( + r""" ^<pre> \s* $ (?P<pre_block> (\n|.)*? ) ^</pre> \s* $ [\s\n]* -''', re.VERBOSE | re.UNICODE | re.MULTILINE) +""", + re.VERBOSE | re.UNICODE | re.MULTILINE, +) -inline_re = re.compile(r''' +inline_re = re.compile( + r""" <pre> (?P<pre_inline> (\n|.)*? ) </pre> -''', re.VERBOSE | re.UNICODE) +""", + re.VERBOSE | re.UNICODE, +) headline_tag_re = re.compile(r"h(\d)", re.UNICODE) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class HtmlParser(HTMLParser): """ parse html code and create a document tree. - + >>> p = HtmlParser() >>> p.feed("<p>html <strong>code</strong></p>") <DocNode document: None> @@ -63,7 +67,7 @@ class HtmlParser(HTMLParser): strong data: 'code' ******************************************************************************** - + >>> p = HtmlParser() >>> p.feed("<p>html1 <script>var foo='<em>BAR</em>';</script> html2</p>") <DocNode document: None> @@ -78,6 +82,7 @@ class HtmlParser(HTMLParser): data: ' html2' ******************************************************************************** """ + # placeholder html tag for pre cutout areas: _block_placeholder = "blockdata" _inline_placeholder = "inlinedata" @@ -87,9 +92,7 @@ class HtmlParser(HTMLParser): self.debugging = debug if self.debugging: - warnings.warn( - message="Html2Creole debug is on! warn every data append." - ) + warnings.warn(message="Html2Creole debug is on! warn every data append.") self.result = DebugList(self) else: self.result = [] @@ -103,11 +106,11 @@ class HtmlParser(HTMLParser): def _pre_cut(self, data, type, placeholder): if self.debugging: - print("append blockdata: %r" % data) - assert isinstance(data, TEXT_TYPE), "blockdata is not unicode" + print(f"append blockdata: {data!r}") + assert isinstance(data, str), "blockdata is not unicode" self.blockdata.append(data) id = len(self.blockdata) - 1 - return '<%s type="%s" id="%s" />' % (placeholder, type, id) + return f'<{placeholder} type="{type}" id="{id}" />' def _pre_pre_inline_cut(self, groups): return self._pre_cut(groups["pre_inline"], "pre", self._inline_placeholder) @@ -127,13 +130,13 @@ class HtmlParser(HTMLParser): if text is not None: if self.debugging: print("%15s: %r (%r)" % (name, text, match.group(0))) - method = getattr(self, '_pre_%s_cut' % name) + method = getattr(self, f"_pre_{name}_cut") return method(groups) -# data = match.group("data") + # data = match.group("data") def feed(self, raw_data): - assert isinstance(raw_data, TEXT_TYPE), "feed data must be unicode!" + assert isinstance(raw_data, str), "feed data must be unicode!" data = raw_data.strip() # cut out <pre> and <tt> areas block tag areas @@ -151,15 +154,14 @@ class HtmlParser(HTMLParser): print("cleaned data:") print(data) print("-" * 79) -# print(clean_data.replace(">", ">\n")) -# print("-"*79) + # print(clean_data.replace(">", ">\n")) + # print("-"*79) HTMLParser.feed(self, data) return self.root - - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def _upto(self, node, kinds): """ @@ -179,19 +181,17 @@ class HtmlParser(HTMLParser): self.cur = self._upto(self.cur, kinds) self.debug_msg("go up to", self.cur) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def handle_starttag(self, tag, attrs): - self.debug_msg("starttag", "%r atts: %s" % (tag, attrs)) + self.debug_msg("starttag", f"{tag!r} atts: {attrs}") if tag in IGNORE_TAGS: return headline = headline_tag_re.match(tag) if headline: - self.cur = DocNode( - "headline", self.cur, level=int(headline.group(1)) - ) + self.cur = DocNode("headline", self.cur, level=int(headline.group(1))) return if tag in ("li", "ul", "ol"): @@ -207,30 +207,30 @@ class HtmlParser(HTMLParser): self.cur = DocNode(tag, self.cur, None, attrs) def handle_data(self, data): - self.debug_msg("data", "%r" % data) - if isinstance(data, BINARY_TYPE): + self.debug_msg("data", f"{data!r}") + if isinstance(data, bytes): data = unicode(data) DocNode("data", self.cur, content=data) def handle_charref(self, name): - self.debug_msg("charref", "%r" % name) + self.debug_msg("charref", f"{name!r}") DocNode("charref", self.cur, content=name) def handle_entityref(self, name): - self.debug_msg("entityref", "%r" % name) + self.debug_msg("entityref", f"{name!r}") DocNode("entityref", self.cur, content=name) def handle_startendtag(self, tag, attrs): - self.debug_msg("startendtag", "%r atts: %s" % (tag, attrs)) + self.debug_msg("startendtag", f"{tag!r} atts: {attrs}") attr_dict = dict(attrs) if tag in (self._block_placeholder, self._inline_placeholder): id = int(attr_dict["id"]) -# block_type = attr_dict["type"] + # block_type = attr_dict["type"] DocNode( - "%s_%s" % (tag, attr_dict["type"]), + f"{tag}_{attr_dict['type']}", self.cur, content=self.blockdata[id], -# attrs = attr_dict + # attrs = attr_dict ) else: DocNode(tag, self.cur, None, attrs) @@ -239,9 +239,9 @@ class HtmlParser(HTMLParser): if tag in IGNORE_TAGS: return - self.debug_msg("endtag", "%r" % tag) + self.debug_msg("endtag", f"{tag!r}") - if tag == "br": # handled in starttag + if tag == "br": # handled in starttag return self.debug_msg("starttag", "%r" % self.get_starttag_text()) @@ -254,7 +254,7 @@ class HtmlParser(HTMLParser): else: self.cur = self.cur.parent - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def debug_msg(self, method, txt): if not self.debugging: @@ -271,35 +271,38 @@ class HtmlParser(HTMLParser): start_node = self.root print(" document tree:") else: - print(" tree from %s:" % start_node) + print(f" tree from {start_node}:") print("=" * 80) + def emit(node, ident=0): for child in node.children: txt = "%s%s" % (" " * ident, child.kind) if child.content: - txt += ": %r" % child.content + txt += f": {child.content!r}" if child.attrs: - txt += " - attrs: %r" % child.attrs + txt += f" - attrs: {child.attrs!r}" if child.level != None: - txt += " - level: %r" % child.level + txt += f" - level: {child.level!r}" print(txt) emit(child, ident + 4) + emit(start_node) print("*" * 80) -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) # p = HtmlParser(debug=True) # p.feed("""\ -#<p><span>in span</span><br /> -#<code>in code</code></p> -#""") +# <p><span>in span</span><br /> +# <code>in code</code></p> +# """) # p.debug() diff --git a/creole/parser/html_parser_config.py b/creole/parser/html_parser_config.py index 9790833..5236f02 100644 --- a/creole/parser/html_parser_config.py +++ b/creole/parser/html_parser_config.py @@ -4,22 +4,45 @@ """ python-creole ~~~~~~~~~~~~~ - + created by Jens Diemer :copyleft: 2009-2011 by the python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + BLOCK_TAGS = ( - "address", "blockquote", "center", "dir", "div", "dl", "fieldset", + "address", + "blockquote", + "center", + "dir", + "div", + "dl", + "fieldset", "form", - "h1", "h2", "h3", "h4", "h5", "h6", - "hr", "ins", "isindex", "men", "noframes", "noscript", - "ul", "ol", "li", "table", "th", "tr", "td", - "p", "pre", - "br" + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "hr", + "ins", + "isindex", + "men", + "noframes", + "noscript", + "ul", + "ol", + "li", + "table", + "th", + "tr", + "td", + "p", + "pre", + "br", ) IGNORE_TAGS = ("tbody",) diff --git a/creole/py3compat.py b/creole/py3compat.py deleted file mode 100644 index f48da75..0000000 --- a/creole/py3compat.py +++ /dev/null @@ -1,43 +0,0 @@ -# coding: utf-8 - -""" - Helper to support Python v2 and v3 - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Some ideas borrowed from six - - See also: - http://python3porting.com - https://bitbucket.org/gutworth/six/src/tip/six.py - http://packages.python.org/six/ -""" - -from __future__ import division, absolute_import, print_function, unicode_literals - -import sys -import doctest -import re - -# True if we are running on Python 3. -PY3 = sys.version_info[0] == 3 - - -if PY3: - TEXT_TYPE = str - BINARY_TYPE = bytes -else: - TEXT_TYPE = unicode - BINARY_TYPE = str - - # Simple remove 'u' from python 2 unicode repr string - # See also: - # http://bugs.python.org/issue3955 - # http://www.python-forum.de/viewtopic.php?f=1&t=27509 (de) - origin_OutputChecker = doctest.OutputChecker - class OutputChecker2(origin_OutputChecker): - def check_output(self, want, got, optionflags): - got = got.replace("u'", "'").replace('u"', '"') - return origin_OutputChecker.check_output(self, want, got, optionflags) - doctest.OutputChecker = OutputChecker2 - - diff --git a/creole/rest_tools/clean_writer.py b/creole/rest_tools/clean_writer.py index 5378bd7..4d284fb 100644 --- a/creole/rest_tools/clean_writer.py +++ b/creole/rest_tools/clean_writer.py @@ -4,25 +4,25 @@ """ A clean reStructuredText html writer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + It will produce a minimal set of html output. (No extry divs, classes oder ids.) - + Some code stolen from: http://www.arnebrodowski.de/blog/write-your-own-restructuredtext-writer.html https://github.com/alex-morega/docutils-plainhtml/blob/master/plain_html_writer.py - + :copyleft: 2011-2013 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -#import warnings + +# import warnings import sys from creole.exceptions import DocutilsImportError -from creole.py3compat import TEXT_TYPE, PY3 + try: import docutils @@ -30,10 +30,7 @@ try: from docutils.writers import html4css1 except ImportError: etype, evalue, etb = sys.exc_info() - msg = ( - "%s - You can't use rest2html!" - " Please install: http://pypi.python.org/pypi/docutils" - ) % evalue + msg = ("%s - You can't use rest2html!" " Please install: http://pypi.python.org/pypi/docutils") % evalue evalue = etype(msg) # Doesn't work with Python 3: @@ -43,22 +40,23 @@ except ImportError: raise DocutilsImportError(msg) - DEBUG = False -#DEBUG = True +# DEBUG = True IGNORE_ATTR = ( - "start", "class", "frame", "rules", -) -IGNORE_TAGS = ( - "div", + "start", + "class", + "frame", + "rules", ) +IGNORE_TAGS = ("div",) class CleanHTMLWriter(html4css1.Writer): """ This docutils writer will use the CleanHTMLTranslator class below. """ + def __init__(self): html4css1.Writer.__init__(self) self.translator_class = CleanHTMLTranslator @@ -68,19 +66,20 @@ class CleanHTMLTranslator(html4css1.HTMLTranslator, object): """ Clean html translator for docutils system. """ + def _do_nothing(self, node, *args, **kwargs): pass - def starttag(self, node, tagname, suffix='\n', empty=0, **attributes): + def starttag(self, node, tagname, suffix="\n", empty=0, **attributes): """ create start tag with the filter IGNORE_TAGS and IGNORE_ATTR. """ -# return super(CleanHTMLTranslator, self).starttag(node, tagname, suffix, empty, **attributes) -# return "XXX%r" % tagname + # return super(CleanHTMLTranslator, self).starttag(node, tagname, suffix, empty, **attributes) + # return "XXX%r" % tagname if tagname in IGNORE_TAGS: if DEBUG: - print("ignore tag %r" % tagname) + print(f"ignore tag {tagname!r}") return "" parts = [tagname] @@ -95,23 +94,23 @@ class CleanHTMLTranslator(html4css1.HTMLTranslator, object): continue if isinstance(value, list): - value = ' '.join([TEXT_TYPE(x) for x in value]) + value = " ".join([str(x) for x in value]) - part = '%s="%s"' % (name.lower(), self.attval(TEXT_TYPE(value))) + part = f'{name.lower()}="{self.attval(str(value))}"' parts.append(part) if DEBUG: - print("Tag %r - ids: %r - attributes: %r - parts: %r" % ( - tagname, getattr(node, "ids", "-"), attributes, parts - )) + print( + f"Tag {tagname!r} - ids: {getattr(node, 'ids', '-')!r} - attributes: {attributes!r} - parts: {parts!r}" + ) if empty: - infix = ' /' + infix = " /" else: - infix = '' - html = '<%s%s>%s' % (' '.join(parts), infix, suffix) + infix = "" + html = f"<{' '.join(parts)}{infix}>{suffix}" if DEBUG: - print("startag html: %r" % html) + print(f"startag html: {html!r}") return html def visit_section(self, node): @@ -129,13 +128,12 @@ class CleanHTMLTranslator(html4css1.HTMLTranslator, object): # set only html_body, we used in rest2html() and don't surround it with <div> def depart_document(self, node): - self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo - + self.docinfo + self.body - + self.body_suffix[:-1]) - assert not self.context, 'len(context) = %s' % len(self.context) + self.html_body.extend( + self.body_prefix[1:] + self.body_pre_docinfo + self.docinfo + self.body + self.body_suffix[:-1] + ) + assert not self.context, "len(context) = %s" % len(self.context) - - #__________________________________________________________________________ + # __________________________________________________________________________ # Clean table: visit_thead = _do_nothing @@ -147,7 +145,7 @@ class CleanHTMLTranslator(html4css1.HTMLTranslator, object): if docutils.__version__ > "0.10": self.context.append(self.compact_p) self.compact_p = True - self.body.append(self.starttag(node, 'table')) + self.body.append(self.starttag(node, "table")) def visit_tgroup(self, node): node.stubs = [] @@ -155,60 +153,56 @@ class CleanHTMLTranslator(html4css1.HTMLTranslator, object): def visit_field_list(self, node): super(CleanHTMLTranslator, self).visit_field_list(node) if "<col" in self.body[-1]: - del(self.body[-1]) + del self.body[-1] def depart_field_list(self, node): - self.body.append('</table>\n') + self.body.append("</table>\n") self.compact_field_list, self.compact_p = self.context.pop() def visit_docinfo(self, node): - self.body.append(self.starttag(node, 'table')) + self.body.append(self.starttag(node, "table")) def depart_docinfo(self, node): - self.body.append('</table>\n') + self.body.append("</table>\n") - #__________________________________________________________________________ + # __________________________________________________________________________ # Clean image: depart_figure = _do_nothing def visit_image(self, node): super(CleanHTMLTranslator, self).visit_image(node) - if self.body[-1].startswith('<img'): + if self.body[-1].startswith("<img"): align = None - if 'align' in node: + if "align" in node: # image with alignment - align = node['align'] + align = node["align"] - elif node.parent.tagname == 'figure' and 'align' in node.parent: + elif node.parent.tagname == "figure" and "align" in node.parent: # figure with alignment - align = node.parent['align'] + align = node.parent["align"] if align: - self.body[-1] = self.body[-1].replace(' />', ' align="%s" />' % align) - + self.body[-1] = self.body[-1].replace(" />", f' align="{align}" />') def rest2html(content, enable_exit_status=None, **kwargs): """ Convert reStructuredText markup to clean html code: No extra div, class or ids. - + >>> rest2html("- bullet list") '<ul>\\n<li>bullet list</li>\\n</ul>\\n' - + >>> rest2html("A ReSt link to `PyLucid CMS <http://www.pylucid.org>`_ :)") '<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' - + >>> rest2html("========", enable_exit_status=1, traceback=False, exit_status_level=2) Traceback (most recent call last): ... SystemExit: 13 """ - if not PY3: - content = unicode(content) - - assert isinstance(content, TEXT_TYPE), "rest2html content must be %s, but it's %s" % (TEXT_TYPE, type(content)) + assert isinstance(content, str), f"rest2html content must be {str}, but it's {type(content)}" settings_overrides = { "input_encoding": "unicode", @@ -224,32 +218,35 @@ def rest2html(content, enable_exit_status=None, **kwargs): settings_overrides=settings_overrides, enable_exit_status=enable_exit_status, ) -# import pprint -# pprint.pprint(parts) - return parts["html_body"] # Don't detache the first heading + # import pprint + # pprint.pprint(parts) + return parts["html_body"] # Don't detache the first heading -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) -# print(rest2html(""") -#+------------+------------+ -#| Headline 1 | Headline 2 | -#+============+============+ -#| cell one | cell two | -#+------------+------------+ -# """) - -# print(rest2html(""") -#:homepage: -# http://code.google.com/p/python-creole/ -# -#:sourcecode: -# http://github.com/jedie/python-creole -# """) - - print(rest2html(""" + # print(rest2html(""") + # +------------+------------+ + # | Headline 1 | Headline 2 | + # +============+============+ + # | cell one | cell two | + # +------------+------------+ + # """) + + # print(rest2html(""") + #:homepage: + # http://code.google.com/p/python-creole/ + # + #:sourcecode: + # http://github.com/jedie/python-creole + # """) + + print( + rest2html( + """ =============== Section Title 1 =============== @@ -269,4 +266,6 @@ Section Title 5 Section Title 6 ''''''''''''''' - """)) + """ + ) + ) diff --git a/creole/rest_tools/pypi_rest2html.py b/creole/rest_tools/pypi_rest2html.py index fd7d16d..287993b 100644 --- a/creole/rest_tools/pypi_rest2html.py +++ b/creole/rest_tools/pypi_rest2html.py @@ -11,17 +11,14 @@ https://bitbucket.org/pypa/pypi/issue/161/rest-formatting-fails-and-there-is-no-way """ -from __future__ import division, absolute_import, print_function - -try: - # Python 3 - from urllib.parse import urlparse -except ImportError: - # Python 2 - from urlparse import urlparse from creole.exceptions import DocutilsImportError + +from urllib.parse import urlparse + + + try: import docutils from docutils import io, readers @@ -29,65 +26,61 @@ try: from docutils.writers import get_writer_class from docutils.transforms import TransformError, Transform except ImportError as err: - msg = ( - "%s - You can't use rest2html!" - " Please install: http://pypi.python.org/pypi/docutils" - ) % err + msg = ("%s - You can't use rest2html!" " Please install: http://pypi.python.org/pypi/docutils") % err raise DocutilsImportError(msg) -ALLOWED_SCHEMES = '''file ftp gopher hdl http https imap mailto mms news nntp +ALLOWED_SCHEMES = """file ftp gopher hdl http https imap mailto mms news nntp prospero rsync rtsp rtspu sftp shttp sip sips snews svn svn+ssh telnet -wais irc'''.split() +wais irc""".split() -def pypi_rest2html(source, output_encoding='unicode'): +def pypi_rest2html(source, output_encoding="unicode"): """ >>> pypi_rest2html("test!") '<p>test!</p>\\n' """ settings_overrides = { - 'raw_enabled': 0, # no raw HTML code - 'file_insertion_enabled': 0, # no file/URL access - 'halt_level': 2, # at warnings or errors, raise an exception - 'report_level': 5, # never report problems with the reST code - } + "raw_enabled": 0, # no raw HTML code + "file_insertion_enabled": 0, # no file/URL access + "halt_level": 2, # at warnings or errors, raise an exception + "report_level": 5, # never report problems with the reST code + } # Convert reStructuredText to HTML using Docutils. - document = publish_doctree(source=source, - settings_overrides=settings_overrides) + document = publish_doctree(source=source, settings_overrides=settings_overrides) for node in document.traverse(): - if node.tagname == '#text': + if node.tagname == "#text": continue - if node.hasattr('refuri'): - uri = node['refuri'] - elif node.hasattr('uri'): - uri = node['uri'] + if node.hasattr("refuri"): + uri = node["refuri"] + elif node.hasattr("uri"): + uri = node["uri"] else: continue o = urlparse(uri) if o.scheme not in ALLOWED_SCHEMES: - raise TransformError('link scheme not allowed') + raise TransformError("link scheme not allowed") # now turn the transformed document into HTML - reader = readers.doctree.Reader(parser_name='null') - pub = Publisher(reader, source=io.DocTreeInput(document), - destination_class=io.StringOutput) - pub.set_writer('html') + reader = readers.doctree.Reader(parser_name="null") + pub = Publisher(reader, source=io.DocTreeInput(document), destination_class=io.StringOutput) + pub.set_writer("html") pub.process_programmatic_settings(None, settings_overrides, None) pub.set_destination(None, None) pub.publish() parts = pub.writer.parts - output = parts['body'] + output = parts["body"] - if output_encoding != 'unicode': + if output_encoding != "unicode": output = output.encode(output_encoding) return output -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/setup_utils.py b/creole/setup_utils.py index 977cb73..68d9b45 100644 --- a/creole/setup_utils.py +++ b/creole/setup_utils.py @@ -42,7 +42,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import codecs import os @@ -50,13 +50,17 @@ import sys import warnings from creole import creole2html, html2rest -from creole.shared.unknown_tags import raise_unknown_node, transparent_unknown_nodes -from creole.py3compat import PY3 +from creole.shared.unknown_tags import raise_unknown_node, transparent_unknown_nodes RAISE_ERRORS_ARGS = ( - "check", "register", "sdist", "bdist", "upload", - "--long-description", "--restructuredtext", + "check", + "register", + "sdist", + "bdist", + "upload", + "--long-description", + "--restructuredtext", ) @@ -99,34 +103,27 @@ def get_long_description(package_root, filename="README.creole", raise_errors=No long_description_html = creole2html(long_description_origin) # convert html to ReSt - long_description_rest_unicode = html2rest( - long_description_html, - emitter_kwargs={"unknown_emit":unknown_emit} - ) - if PY3: - long_description_rest = long_description_rest_unicode - else: - long_description_rest = long_description_rest_unicode.encode("utf-8") + long_description_rest_unicode = html2rest(long_description_html, emitter_kwargs={"unknown_emit": unknown_emit}) + long_description_rest = long_description_rest_unicode except Exception: if raise_errors: raise # Don't raise the error e.g. in ./setup install process evalue = sys.exc_info()[1] - long_description_rest = "[Error: %s]\n%s" % ( - evalue, long_description_origin - ) + long_description_rest = f"[Error: {evalue}]\n{long_description_origin}" else: if raise_errors: # Test created ReSt code like PyPi does it. from creole.rest_tools.pypi_rest2html import pypi_rest2html + try: pypi_rest2html(long_description_rest_unicode) except SystemExit as e: - msg = "Error creole2rest self test failed: rest2html() exist with status code: %s\n" % e.args[0] + msg = f"Error creole2rest self test failed: rest2html() exist with status code: {e.args[0]}\n" sys.stderr.write(msg) sys.exit(msg) except Exception as e: - sys.exit("ReSt2html error: %s" % e) + sys.exit(f"ReSt2html error: {e}") else: if "check" in sys.argv: print("Generating creole to ReSt to html, ok.") @@ -141,11 +138,12 @@ def _get_long_description(*args, **kwargs): else: warnings.warn(msg, DeprecationWarning) return get_long_description(*args, **kwargs) -GetLongDescription = _get_long_description # for backward-compatibility + + +GetLongDescription = _get_long_description # for backward-compatibility if __name__ == "__main__": package_root = os.path.abspath("../") long_description = get_long_description(package_root) print(long_description) - diff --git a/creole/shared/HTMLParsercompat.py b/creole/shared/HTMLParsercompat.py index 67529d8..31fed20 100644 --- a/creole/shared/HTMLParsercompat.py +++ b/creole/shared/HTMLParsercompat.py @@ -1,7 +1,7 @@ """ Patched version of the original from: http://hg.python.org/cpython/file/tip/Lib/html/parser.py - + compare: http://hg.python.org/cpython/file/2.7/Lib/HTMLParser.py http://hg.python.org/cpython/file/3.2/Lib/html/parser.py @@ -13,13 +13,18 @@ e.g.: meld HTMLParser.py parser.py Make it compatible with Python 2.x and 3.x - + More info see html_parser.py ! """ # ------------------------------------------------------------------- add start -from __future__ import division, absolute_import, print_function, unicode_literals -from creole.py3compat import PY3 + + +# --------------------------------------------------------------- changes end +import re + + + # --------------------------------------------------------------------- add end """A parser for HTML and XHTML.""" @@ -34,40 +39,37 @@ from creole.py3compat import PY3 # --------------------------------------------------------------- changes start try: - import _markupbase # python 3 + import _markupbase # python 3 except ImportError: - import markupbase as _markupbase # python 2 -# --------------------------------------------------------------- changes end -import re + import markupbase as _markupbase # python 2 # Regular expressions used for parsing -interesting_normal = re.compile('[&<]') -incomplete = re.compile('&[a-zA-Z#]') +interesting_normal = re.compile("[&<]") +incomplete = re.compile("&[a-zA-Z#]") -entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]') -charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]') +entityref = re.compile("&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]") +charref = re.compile("&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]") -starttagopen = re.compile('<[a-zA-Z]') -piclose = re.compile('>') -commentclose = re.compile(r'--\s*>') -tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') +starttagopen = re.compile("<[a-zA-Z]") +piclose = re.compile(">") +commentclose = re.compile(r"--\s*>") +tagfind = re.compile("([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*") # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state -tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') +tagfind_tolerant = re.compile("[a-zA-Z][^\t\n\r\f />\x00]*") # Note: # 1) the strict attrfind isn't really strict, but we can't make it # correctly strict without breaking backward compatibility; # 2) if you change attrfind remember to update locatestarttagend too; # 3) if you change attrfind and/or locatestarttagend the parser will # explode, so don't do it. -attrfind = re.compile( - r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' - r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?') +attrfind = re.compile(r"\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*" r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?') attrfind_tolerant = re.compile( - r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' - r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') -locatestarttagend = re.compile(r""" + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*' +) +locatestarttagend = re.compile( + r""" <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name (?:\s+ # whitespace before attribute name (?:[a-zA-Z_][-.:a-zA-Z0-9_]* # attribute name @@ -80,8 +82,11 @@ locatestarttagend = re.compile(r""" ) )* \s* # trailing whitespace -""", re.VERBOSE) -locatestarttagend_tolerant = re.compile(r""" +""", + re.VERBOSE, +) +locatestarttagend_tolerant = re.compile( + r""" <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name (?:[\s/]* # optional whitespace before attribute name (?:(?<=['"\s/])[^\s/>][^\s/=>]* # attribute name @@ -95,11 +100,13 @@ locatestarttagend_tolerant = re.compile(r""" )* )? \s* # trailing whitespace -""", re.VERBOSE) -endendtag = re.compile('>') +""", + re.VERBOSE, +) +endendtag = re.compile(">") # the HTML 5 spec, section 8.1.2.2, doesn't allow spaces between # </ and the tag name, so maybe this should be fixed -endtagfind = re.compile('</\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\s*>') +endtagfind = re.compile("</\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\s*>") class HTMLParseError(Exception): @@ -114,7 +121,7 @@ class HTMLParseError(Exception): def __str__(self): result = self.msg if self.lineno is not None: - result = result + ", at line %d" % self.lineno + result = result + f", at line {self.lineno:d}" if self.offset is not None: result = result + ", column %d" % (self.offset + 1) return result @@ -155,8 +162,8 @@ class HTMLParser(_markupbase.ParserBase): def reset(self): """Reset this instance. Loses all unprocessed data.""" - self.rawdata = '' - self.lasttag = '???' + self.rawdata = "" + self.lasttag = "???" self.interesting = interesting_normal self.cdata_elem = None _markupbase.ParserBase.reset(self) @@ -185,7 +192,7 @@ class HTMLParser(_markupbase.ParserBase): def set_cdata_mode(self, elem): self.cdata_elem = elem.lower() - self.interesting = re.compile(r'</\s*%s\s*>' % self.cdata_elem, re.I) + self.interesting = re.compile(r"</\s*%s\s*>" % self.cdata_elem, re.I) def clear_cdata_mode(self): self.interesting = interesting_normal @@ -199,19 +206,21 @@ class HTMLParser(_markupbase.ParserBase): i = 0 n = len(rawdata) while i < n: - match = self.interesting.search(rawdata, i) # < or & + match = self.interesting.search(rawdata, i) # < or & if match: j = match.start() else: if self.cdata_elem: break j = n - if i < j: self.handle_data(rawdata[i:j]) + if i < j: + self.handle_data(rawdata[i:j]) i = self.updatepos(i, j) - if i == n: break + if i == n: + break startswith = rawdata.startswith - if startswith('<', i): - if starttagopen.match(rawdata, i): # < + letter + if startswith("<", i): + if starttagopen.match(rawdata, i): # < + letter k = self.parse_starttag(i) elif startswith("</", i): k = self.parse_endtag(i) @@ -234,9 +243,9 @@ class HTMLParser(_markupbase.ParserBase): break if self.strict: self.error("EOF in middle of construct") - k = rawdata.find('>', i + 1) + k = rawdata.find(">", i + 1) if k < 0: - k = rawdata.find('<', i + 1) + k = rawdata.find("<", i + 1) if k < 0: k = i + 1 else: @@ -249,22 +258,22 @@ class HTMLParser(_markupbase.ParserBase): name = match.group()[2:-1] self.handle_charref(name) k = match.end() - if not startswith(';', k-1): + if not startswith(";", k - 1): k = k - 1 i = self.updatepos(i, k) continue else: - if ";" in rawdata[i:]: #bail by consuming &# + if ";" in rawdata[i:]: # bail by consuming &# self.handle_data(rawdata[0:2]) i = self.updatepos(i, 2) break - elif startswith('&', i): + elif startswith("&", i): match = entityref.match(rawdata, i) if match: name = match.group(1) self.handle_entityref(name) k = match.end() - if not startswith(';', k-1): + if not startswith(";", k - 1): k = k - 1 i = self.updatepos(i, k) continue @@ -300,20 +309,20 @@ class HTMLParser(_markupbase.ParserBase): # See also parse_declaration in _markupbase def parse_html_declaration(self, i): rawdata = self.rawdata - if rawdata[i:i+2] != '<!': - self.error('unexpected call to parse_html_declaration()') - if rawdata[i:i+4] == '<!--': + if rawdata[i : i + 2] != "<!": + self.error("unexpected call to parse_html_declaration()") + if rawdata[i : i + 4] == "<!--": # this case is actually already handled in goahead() return self.parse_comment(i) - elif rawdata[i:i+3] == '<![': + elif rawdata[i : i + 3] == "<![": return self.parse_marked_section(i) - elif rawdata[i:i+9].lower() == '<!doctype': + elif rawdata[i : i + 9].lower() == "<!doctype": # find the closing > - gtpos = rawdata.find('>', i+9) + gtpos = rawdata.find(">", i + 9) if gtpos == -1: return -1 - self.handle_decl(rawdata[i+2:gtpos]) - return gtpos+1 + self.handle_decl(rawdata[i + 2 : gtpos]) + return gtpos + 1 else: return self.parse_bogus_comment(i) @@ -321,24 +330,24 @@ class HTMLParser(_markupbase.ParserBase): # see http://www.w3.org/TR/html5/tokenization.html#bogus-comment-state def parse_bogus_comment(self, i, report=1): rawdata = self.rawdata - if rawdata[i:i+2] not in ('<!', '</'): - self.error('unexpected call to parse_comment()') - pos = rawdata.find('>', i+2) + if rawdata[i : i + 2] not in ("<!", "</"): + self.error("unexpected call to parse_comment()") + pos = rawdata.find(">", i + 2) if pos == -1: return -1 if report: - self.handle_comment(rawdata[i+2:pos]) + self.handle_comment(rawdata[i + 2 : pos]) return pos + 1 # Internal -- parse processing instr, return end or -1 if not terminated def parse_pi(self, i): rawdata = self.rawdata - assert rawdata[i:i+2] == '<?', 'unexpected call to parse_pi()' - match = piclose.search(rawdata, i+2) # > + assert rawdata[i : i + 2] == "<?", "unexpected call to parse_pi()" + match = piclose.search(rawdata, i + 2) # > if not match: return -1 j = match.start() - self.handle_pi(rawdata[i+2: j]) + self.handle_pi(rawdata[i + 2 : j]) j = match.end() return j @@ -353,8 +362,8 @@ class HTMLParser(_markupbase.ParserBase): # Now parse the data between i+1 and j into a tag and attrs attrs = [] - match = tagfind.match(rawdata, i+1) - assert match, 'unexpected call to parse_starttag()' + match = tagfind.match(rawdata, i + 1) + assert match, "unexpected call to parse_starttag()" k = match.end() self.lasttag = tag = match.group(1).lower() while k < endpos: @@ -367,8 +376,7 @@ class HTMLParser(_markupbase.ParserBase): attrname, rest, attrvalue = m.group(1, 2, 3) if not rest: attrvalue = None - elif attrvalue[:1] == '\'' == attrvalue[-1:] or \ - attrvalue[:1] == '"' == attrvalue[-1:]: + elif attrvalue[:1] == "'" == attrvalue[-1:] or attrvalue[:1] == '"' == attrvalue[-1:]: attrvalue = attrvalue[1:-1] if attrvalue: attrvalue = self.unescape(attrvalue) @@ -380,16 +388,14 @@ class HTMLParser(_markupbase.ParserBase): lineno, offset = self.getpos() if "\n" in self.__starttag_text: lineno = lineno + self.__starttag_text.count("\n") - offset = len(self.__starttag_text) \ - - self.__starttag_text.rfind("\n") + offset = len(self.__starttag_text) - self.__starttag_text.rfind("\n") else: offset = offset + len(self.__starttag_text) if self.strict: - self.error("junk characters in start tag: %r" - % (rawdata[k:endpos][:20],)) + self.error(f"junk characters in start tag: {rawdata[k:endpos][:20]!r}") self.handle_data(rawdata[i:endpos]) return endpos - if end.endswith('/>'): + if end.endswith("/>"): # XHTML-style empty tag: <span attr="value" /> self.handle_startendtag(tag, attrs) else: @@ -408,7 +414,7 @@ class HTMLParser(_markupbase.ParserBase): m = locatestarttagend_tolerant.match(rawdata, i) if m: j = m.end() - next = rawdata[j:j+1] + next = rawdata[j : j + 1] if next == ">": return j + 1 if next == "/": @@ -428,8 +434,7 @@ class HTMLParser(_markupbase.ParserBase): if next == "": # end of input return -1 - if next in ("abcdefghijklmnopqrstuvwxyz=/" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"): + if next in ("abcdefghijklmnopqrstuvwxyz=/" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"): # end of input in or before attribute value, or we have the # '/' from a '/>' ending return -1 @@ -445,24 +450,24 @@ class HTMLParser(_markupbase.ParserBase): # Internal -- parse endtag, return end or -1 if incomplete def parse_endtag(self, i): rawdata = self.rawdata - assert rawdata[i:i+2] == "</", "unexpected call to parse_endtag" - match = endendtag.search(rawdata, i+1) # > + assert rawdata[i : i + 2] == "</", "unexpected call to parse_endtag" + match = endendtag.search(rawdata, i + 1) # > if not match: return -1 gtpos = match.end() - match = endtagfind.match(rawdata, i) # </ + tag + > + match = endtagfind.match(rawdata, i) # </ + tag + > if not match: if self.cdata_elem is not None: self.handle_data(rawdata[i:gtpos]) return gtpos if self.strict: - self.error("bad end tag: %r" % (rawdata[i:gtpos],)) + self.error(f"bad end tag: {rawdata[i:gtpos]!r}") # find the name: w3.org/TR/html5/tokenization.html#tag-name-state - namematch = tagfind_tolerant.match(rawdata, i+2) + namematch = tagfind_tolerant.match(rawdata, i + 2) if not namematch: # w3.org/TR/html5/tokenization.html#end-tag-open-state - if rawdata[i:i+3] == '</>': - return i+3 + if rawdata[i : i + 3] == "</>": + return i + 3 else: return self.parse_bogus_comment(i) tagname = namematch.group().lower() @@ -470,11 +475,11 @@ class HTMLParser(_markupbase.ParserBase): # Note: this is not 100% correct, since we might have things like # </tag attr=">">, but looking for > after tha name should cover # most of the cases and is much simpler - gtpos = rawdata.find('>', namematch.end()) + gtpos = rawdata.find(">", namematch.end()) self.handle_endtag(tagname) - return gtpos+1 + return gtpos + 1 - elem = match.group(1).lower() # script or style + elem = match.group(1).lower() # script or style if self.cdata_elem is not None: if elem != self.cdata_elem: self.handle_data(rawdata[i:gtpos]) @@ -523,67 +528,42 @@ class HTMLParser(_markupbase.ParserBase): def unknown_decl(self, data): if self.strict: - self.error("unknown declaration: %r" % (data,)) + self.error(f"unknown declaration: {data!r}") # Internal -- helper to remove special character quoting entitydefs = None + def unescape(self, s): - if '&' not in s: + if "&" not in s: return s # -------------------------------------------------------- change start - if PY3: - def replaceEntities(s): - s = s.groups()[0] - try: - if s[0] == "#": - s = s[1:] - if s[0] in ['x','X']: - c = int(s[1:], 16) - else: - c = int(s) - return chr(c) - except ValueError: - return '&#'+ s +';' - else: - # Cannot use name2codepoint directly, because HTMLParser - # supports apos, which is not part of HTML 4 - import html.entities - if HTMLParser.entitydefs is None: - entitydefs = HTMLParser.entitydefs = {'apos':"'"} - for k, v in html.entities.name2codepoint.items(): - entitydefs[k] = chr(v) - try: - return self.entitydefs[s] - except KeyError: - return '&'+s+';' - - return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", - replaceEntities, s, flags=re.ASCII) - else: - def replaceEntities(s): - s = s.groups()[0] + + def replaceEntities(s): + s = s.groups()[0] + try: + if s[0] == "#": + s = s[1:] + if s[0] in ["x", "X"]: + c = int(s[1:], 16) + else: + c = int(s) + return chr(c) + except ValueError: + return "&#" + s + ";" + else: + # Cannot use name2codepoint directly, because HTMLParser + # supports apos, which is not part of HTML 4 + import html.entities + + if HTMLParser.entitydefs is None: + entitydefs = HTMLParser.entitydefs = {"apos": "'"} + for k, v in html.entities.name2codepoint.items(): + entitydefs[k] = chr(v) try: - if s[0] == "#": - s = s[1:] - if s[0] in ['x','X']: - c = int(s[1:], 16) - else: - c = int(s) - return unichr(c) - except ValueError: - return '&#'+s+';' - else: - # Cannot use name2codepoint directly, because HTMLParser supports apos, - # which is not part of HTML 4 - import htmlentitydefs - if HTMLParser.entitydefs is None: - entitydefs = HTMLParser.entitydefs = {'apos':"'"} - for k, v in htmlentitydefs.name2codepoint.iteritems(): - entitydefs[k] = unichr(v) - try: - return self.entitydefs[s] - except KeyError: - return '&'+s+';' - - return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", replaceEntities, s) - # -------------------------------------------------------- change end
\ No newline at end of file + return self.entitydefs[s] + except KeyError: + return "&" + s + ";" + + return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", replaceEntities, s, flags=re.ASCII) + + # -------------------------------------------------------- change end diff --git a/creole/shared/base_emitter.py b/creole/shared/base_emitter.py index 1561083..7d375f7 100644 --- a/creole/shared/base_emitter.py +++ b/creole/shared/base_emitter.py @@ -10,11 +10,11 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -from creole.parser.html_parser_config import BLOCK_TAGS + from creole.html_tools.deentity import Deentity -from creole.py3compat import TEXT_TYPE +from creole.parser.html_parser_config import BLOCK_TAGS + from creole.shared.markup_table import MarkupTable from creole.shared.unknown_tags import transparent_unknown_nodes @@ -24,6 +24,7 @@ class BaseEmitter(object): Build from a document_tree (html2creole.parser.HtmlParser instance) a creole markup text. """ + def __init__(self, document_tree, unknown_emit=None, debug=False): self.root = document_tree @@ -35,20 +36,20 @@ class BaseEmitter(object): self.last = None self.debugging = debug - self.deentity = Deentity() # for replacing html entities + self.deentity = Deentity() # for replacing html entities self._inner_list = "" self._mask_linebreak = False - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def blockdata_pass_emit(self, node): - return "%s\n\n" % node.content + return f"{node.content}\n\n" return node.content - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def data_emit(self, node): - #node.debug() + # node.debug() return node.content def entityref_emit(self, node): @@ -61,12 +62,10 @@ class BaseEmitter(object): return self.deentity.replace_named(entity) except KeyError as err: if self.debugging: - print("unknown html entity found: %r" % entity) - return "&%s" % entity # FIXME + print(f"unknown html entity found: {entity!r}") + return f"&{entity}" # FIXME except UnicodeDecodeError as err: - raise UnicodeError( - "Error handling entity %r: %s" % (entity, err) - ) + raise UnicodeError(f"Error handling entity {entity!r}: {err}") def charref_emit(self, node): """ @@ -82,7 +81,7 @@ class BaseEmitter(object): # entity as a unicode number return self.deentity.replace_number(entity) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def p_emit(self, node): return "%s\n\n" % self.emit_children(node) @@ -93,16 +92,16 @@ class BaseEmitter(object): else: return "\n" - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _typeface(self, node, key): return key + self.emit_children(node) + key - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def li_emit(self, node): content = self.emit_children(node) - return "\n%s %s" % (self._inner_list, content) + return f"\n{self._inner_list} {content}" def _list_emit(self, node, list_type): start_newline = False @@ -110,7 +109,7 @@ class BaseEmitter(object): if not self.last.content or not self.last.content.endswith("\n"): start_newline = True - if self._inner_list == "": # Start a new list + if self._inner_list == "": # Start a new list self._inner_list = list_type else: self._inner_list += list_type @@ -119,7 +118,7 @@ class BaseEmitter(object): self._inner_list = self._inner_list[:-1] - if self._inner_list == "": # Start a new list + if self._inner_list == "": # Start a new list if start_newline: return "\n" + content + "\n\n" else: @@ -127,17 +126,15 @@ class BaseEmitter(object): else: return content - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def table_emit(self, node): self._table = MarkupTable( - head_prefix=self.table_head_prefix, - auto_width=self.table_auto_width, - debug_msg=self.debug_msg + head_prefix=self.table_head_prefix, auto_width=self.table_auto_width, debug_msg=self.debug_msg ) self.emit_children(node) content = self._table.get_table_markup() - return "%s\n" % content + return f"{content}\n" def tr_emit(self, node): self._table.add_tr() @@ -165,13 +162,13 @@ class BaseEmitter(object): self._table.add_td(content) return "" - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _emit_content(self, node): content = self.emit_children(node) content = self._escape_linebreaks(content) if node.kind in BLOCK_TAGS: - content = "%s\n\n" % content + content = f"{content}\n\n" return content def div_emit(self, node): @@ -180,7 +177,7 @@ class BaseEmitter(object): def span_emit(self, node): return self._emit_content(node) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def document_emit(self, node): self.last = node @@ -196,47 +193,46 @@ class BaseEmitter(object): result = [] for child in node.children: content = self.emit_node(child) - assert isinstance(content, TEXT_TYPE) + assert isinstance(content, str) result.append(content) return result def emit_node(self, node): """Emit a single node.""" + def unicode_error(method_name, method, node, content): node.debug() raise AssertionError( - "Method '%s' (%s) returns no unicode - returns: %s (%s)" % ( - method_name, method, repr(content), type(content) - ) + f"Method '{method_name}' ({method}) returns no unicode - returns: {repr(content)} ({type(content)})" ) if node.level: - self.debug_msg("emit_node", "%s (level: %i): %r" % (node.kind, node.level, node.content)) + self.debug_msg("emit_node", f"{node.kind} (level: {node.level:d}): {node.content!r}") else: - self.debug_msg("emit_node", "%s: %r" % (node.kind, node.content)) + self.debug_msg("emit_node", f"{node.kind}: {node.content!r}") - method_name = "%s_emit" % node.kind + method_name = f"{node.kind}_emit" emit_method = getattr(self, method_name, None) if emit_method: content = emit_method(node) - if not isinstance(content, TEXT_TYPE): + if not isinstance(content, str): unicode_error(method_name, emit_method, node, content) else: content = self._unknown_emit(self, node) - if not isinstance(content, TEXT_TYPE): + if not isinstance(content, str): unicode_error(method_name, self._unknown_emit, node, content) self.last = node return content -# def emit(self): -# """Emit the document represented by self.root DOM tree.""" -# result = self.emit_node(self.root) -## return result.strip() # FIXME -# return result.rstrip() # FIXME + # def emit(self): + # """Emit the document represented by self.root DOM tree.""" + # result = self.emit_node(self.root) + ## return result.strip() # FIXME + # return result.rstrip() # FIXME - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def debug_msg(self, method, txt): if not self.debugging: diff --git a/creole/shared/document_tree.py b/creole/shared/document_tree.py index 527e4f9..4b198ab 100644 --- a/creole/shared/document_tree.py +++ b/creole/shared/document_tree.py @@ -10,22 +10,23 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import warnings + import inspect +import warnings + -from creole.py3compat import TEXT_TYPE from creole.shared.utils import dict2string class DocNode: """ A node in the document tree for html2creole and creole2html. - + The Document tree would be created in the parser and used in the emitter. """ - def __init__(self, kind='', parent=None, content=None, attrs=[], level=None): + + def __init__(self, kind="", parent=None, content=None, attrs=[], level=None): self.kind = kind self.children = [] @@ -35,8 +36,9 @@ class DocNode: self.attrs = dict(attrs) if content: - assert isinstance(content, TEXT_TYPE), "Given content %r is not unicode, it's type: %s" % ( - content, type(content) + assert isinstance(content, str), "Given content %r is not unicode, it's type: %s" % ( + content, + type(content), ) self.content = content @@ -60,8 +62,9 @@ class DocNode: return str(self.__repr__()) def __repr__(self): - return "<DocNode %s: %r>" % (self.kind, self.content) -# return "<DocNode %s (parent: %r): %r>" % (self.kind, self.parent, self.content) + return f"<DocNode {self.kind}: {self.content!r}>" + + # return "<DocNode %s (parent: %r): %r>" % (self.kind, self.parent, self.content) def debug(self): """ @@ -80,7 +83,7 @@ class DocNode: """ print("_" * 80) print("\tDocNode - debug:") - print("str(): %s" % self) + print(f"str(): {self}") print("attributes:") for i in dir(self): if i.startswith("_") or i == "debug": @@ -96,17 +99,15 @@ class DebugList(list): super(DebugList, self).__init__() def append(self, item): -# for stack_frame in inspect.stack(): print(stack_frame) + # for stack_frame in inspect.stack(): print(stack_frame) line, method = inspect.stack()[1][2:4] - msg = "%-8s append: %-35r (%-15s line:%s)" % ( - self.html2creole.getpos(), item, - method, line - ) + msg = "%-8s append: %-35r (%-15s line:%s)" % (self.html2creole.getpos(), item, method, line) warnings.warn(msg) list.append(self, item) -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/shared/example_macros.py b/creole/shared/example_macros.py index 2eb85d8..da9cec9 100644 --- a/creole/shared/example_macros.py +++ b/creole/shared/example_macros.py @@ -11,18 +11,19 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + from xml.sax.saxutils import escape +from creole.shared.utils import get_pygments_formatter, get_pygments_lexer + try: from pygments import highlight + PYGMENTS = True except ImportError: PYGMENTS = False -from creole.shared.utils import get_pygments_lexer, get_pygments_formatter - def html(text): """ @@ -37,7 +38,7 @@ def pre(text): Macro tag <<pre>>...<</pre>>. Put text between html pre tag. """ - return '<pre>%s</pre>' % escape(text) + return "<pre>%s</pre>" % escape(text) def code(ext, text): @@ -49,20 +50,20 @@ def code(ext, text): return pre(text) try: - source_type = '' - if '.' in ext: - source_type = ext.strip().split('.')[1] + source_type = "" + if "." in ext: + source_type = ext.strip().split(".")[1] else: source_type = ext.strip() except IndexError: - source_type = '' + source_type = "" lexer = get_pygments_lexer(source_type, code) formatter = get_pygments_formatter() try: - highlighted_text = highlight(text, lexer, formatter).decode('utf-8') + highlighted_text = highlight(text, lexer, formatter).decode("utf-8") except: highlighted_text = pre(text) finally: - return highlighted_text.replace('\n', '<br />\n') + return highlighted_text.replace("\n", "<br />\n") diff --git a/creole/shared/html_parser.py b/creole/shared/html_parser.py index 0bdb7c4..a8b1410 100644 --- a/creole/shared/html_parser.py +++ b/creole/shared/html_parser.py @@ -21,7 +21,7 @@ try: import HTMLParser as OriginHTMLParser except ImportError: - from html import parser as OriginHTMLParser # python 3 + from html import parser as OriginHTMLParser # python 3 if hasattr(OriginHTMLParser, "cdata_elem"): diff --git a/creole/shared/markup_table.py b/creole/shared/markup_table.py index ec59e66..ef78ced 100644 --- a/creole/shared/markup_table.py +++ b/creole/shared/markup_table.py @@ -1,9 +1,9 @@ - class MarkupTable(object): """ Container for holding table data and render the data in creole markup. Format every cell width to the same col width. """ + def __init__(self, head_prefix="= ", auto_width=True, debug_msg=None): self.head_prefix = head_prefix self.auto_width = auto_width @@ -44,9 +44,9 @@ class MarkupTable(object): cell = cell.strip() if cell != "": if self.head_prefix and cell.startswith(self.head_prefix): - cell += " " # Headline + cell += " " # Headline else: - cell = " %s " % cell # normal cell + cell = f" {cell} " # normal cell line_cells.append(cell) cells.append(line_cells) @@ -81,8 +81,8 @@ class MarkupTable(object): # preformat every table cell cells, widths = self._get_preformat_info() - separator_line = "+%s+" % "+".join(["-"*width for width in widths]) - headline_separator = "+%s+" % "+".join(["="*width for width in widths]) + separator_line = "+%s+" % "+".join(["-" * width for width in widths]) + headline_separator = "+%s+" % "+".join(["=" * width for width in widths]) lines = [] for no, row in enumerate(cells): @@ -99,6 +99,8 @@ class MarkupTable(object): return "\n".join(lines) -if __name__ == '__main__': + +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/shared/unknown_tags.py b/creole/shared/unknown_tags.py index 4e3e079..e7137d5 100644 --- a/creole/shared/unknown_tags.py +++ b/creole/shared/unknown_tags.py @@ -11,7 +11,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + from xml.sax.saxutils import escape @@ -30,33 +30,28 @@ def _mask_content(emitter, node, mask_tag): content = emitter.emit_children(node) if not content: # single tag - return "<<%(mask_tag)s>><%(tag)s%(attrs)s /><</%(mask_tag)s>>" % tag_data + return f"<<{tag_data['mask_tag']}>><{tag_data['tag']}{tag_data['attrs']} /><</{tag_data['mask_tag']}>>" - start_tag = "<<%(mask_tag)s>><%(tag)s%(attrs)s><</%(mask_tag)s>>" % tag_data - end_tag = "<<%(mask_tag)s>></%(tag)s><</%(mask_tag)s>>" % tag_data + start_tag = f"<<{tag_data['mask_tag']}>><{tag_data['tag']}{tag_data['attrs']}><</{tag_data['mask_tag']}>>" + end_tag = f"<<{tag_data['mask_tag']}>></{tag_data['tag']}><</{tag_data['mask_tag']}>>" return start_tag + content + end_tag - def raise_unknown_node(emitter, node): """ unknown_emit callable for Html2CreoleEmitter - + Raise NotImplementedError on unknown tags. """ content = emitter.emit_children(node) - raise NotImplementedError( - "Node from type '%s' is not implemented! (child content: %r)" % ( - node.kind, content - ) - ) + raise NotImplementedError(f"Node from type '{node.kind}' is not implemented! (child content: {content!r})") def use_html_macro(emitter, node): """ unknown_emit callable for Html2CreoleEmitter - + Use the <<html>> macro to mask unknown tags. """ return _mask_content(emitter, node, mask_tag="html") @@ -65,7 +60,7 @@ def use_html_macro(emitter, node): def preformat_unknown_nodes(emitter, node): """ Put unknown tags in a <pre> area. - + Usefull for html2textile.emitter.TextileEmitter() """ return _mask_content(emitter, node, mask_tag="pre") @@ -74,7 +69,7 @@ def preformat_unknown_nodes(emitter, node): def escape_unknown_nodes(emitter, node): """ unknown_emit callable for Html2CreoleEmitter - + All unknown tags should be escaped. """ attrs = node.get_attrs_as_string() @@ -89,18 +84,18 @@ def escape_unknown_nodes(emitter, node): content = emitter.emit_children(node) if not content: # single tag - return escape("<%(tag)s%(attrs)s />" % tag_data) + return escape(f"<{tag_data['tag']}{tag_data['attrs']} />") - start_tag = escape("<%(tag)s%(attrs)s>" % tag_data) - end_tag = escape("</%(tag)s>" % tag_data) + start_tag = escape(f"<{tag_data['tag']}{tag_data['attrs']}>") + end_tag = escape(f"</{tag_data['tag']}>") return start_tag + content + end_tag def transparent_unknown_nodes(emitter, node): """ - unknown_emit callable for Html2CreoleEmitter - + unknown_emit callable for Html2CreoleEmitter + Remove all unknown html tags and show only their child nodes' content. """ diff --git a/creole/shared/utils.py b/creole/shared/utils.py index e150c5f..27adb1a 100644 --- a/creole/shared/utils.py +++ b/creole/shared/utils.py @@ -9,16 +9,17 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import shlex + import json +import shlex + -from creole.py3compat import TEXT_TYPE, PY3 try: from pygments import lexers from pygments.formatters import HtmlFormatter + PYGMENTS = True except ImportError: PYGMENTS = False @@ -31,7 +32,8 @@ KEYWORD_MAP = { "None": None, } -def string2dict(raw_content, encoding="utf-8"): + +def string2dict(content): """ convert a string into a dictionary. e.g.: @@ -43,11 +45,7 @@ def string2dict(raw_content, encoding="utf-8"): See test_creole2html.TestString2Dict() """ - if not PY3 and isinstance(raw_content, TEXT_TYPE): - # shlex.split doesn't work with unicode?!? - raw_content = raw_content.encode(encoding) - - parts = shlex.split(raw_content) + parts = shlex.split(content) result = {} for part in parts: @@ -83,15 +81,13 @@ def dict2string(d): attr_list = [] for key, value in sorted(d.items()): value_string = json.dumps(value) - attr_list.append("%s=%s" % (key, value_string)) + attr_list.append(f"{key}={value_string}") return " ".join(attr_list) def get_pygments_formatter(): if PYGMENTS: - return HtmlFormatter(lineos = True, encoding='utf-8', - style='colorful', outencoding='utf-8', - cssclass='pygments') + return HtmlFormatter(lineos=True, encoding="utf-8", style="colorful", outencoding="utf-8", cssclass="pygments") def get_pygments_lexer(source_type, code): @@ -106,4 +102,5 @@ def get_pygments_lexer(source_type, code): if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/tests/test_TODOs.py b/creole/tests/test_TODOs.py index b396c86..3caa3c4 100644 --- a/creole/tests/test_TODOs.py +++ b/creole/tests/test_TODOs.py @@ -6,8 +6,8 @@ import unittest -from creole.tests.utils.base_unittest import BaseCreoleTest from creole.html_tools.strip_html import strip_html +from creole.tests.utils.base_unittest import BaseCreoleTest class StripHtml(unittest.TestCase): @@ -18,8 +18,8 @@ class StripHtml(unittest.TestCase): @unittest.expectedFailure def test_remove_linebreak(self): - output = strip_html('<strong>foo</strong>\n<ul><li>one</li></ul>') - self.assertEqual(output, '<strong>foo</strong><ul><li>one</li></ul>') + output = strip_html("<strong>foo</strong>\n<ul><li>one</li></ul>") + self.assertEqual(output, "<strong>foo</strong><ul><li>one</li></ul>") class CrossCompareCreoleTests(BaseCreoleTest): @@ -39,7 +39,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): <p>Bold and italics should <i>be<br /> able</i> to <strong>cross<br /> lines.</strong></p> - """ + """, ) @unittest.expectedFailure @@ -47,104 +47,121 @@ class CrossCompareCreoleTests(BaseCreoleTest): """ TODO: bold/italics cross paragraphs in creole2html see: http://code.google.com/p/python-creole/issues/detail?id=13 """ - self.assert_creole2html(""" + self.assert_creole2html( + """ But, should //not be... ...able// to cross paragraphs. - """, """ + """, + """ <p>But, should <em>not be...</em></p> <p>...able<em> to cross paragraphs.</em></p> - """) + """, + ) @unittest.expectedFailure def test_escape_inline(self): """ TODO: different pre/code syntax? """ - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" this is {{{**escaped** inline}}}, isn't it? {{{ a **code** block }}} - """, """ + """, + """ <p>this is <tt>**escaped** inline</tt>, isn't it?</p> <pre> a **code** block </pre> - """) + """, + ) class TestHtml2CreoleMarkup(BaseCreoleTest): @unittest.expectedFailure def test_format_in_a_text(self): """ TODO: http://code.google.com/p/python-creole/issues/detail?id=4 """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" **[[/url/|title]]** - """, """ + """, + """ <a href="/url/"><strong>title</strong></a> - """) + """, + ) @unittest.expectedFailure def test_newline_before_headline(self): """ TODO: http://code.google.com/p/python-creole/issues/detail?id=16#c5 """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" **foo** = one - """, """ + """, + """ <b>foo</b> <h1>one</h1> - """)#, debug=True) + """, + ) # , debug=True) @unittest.expectedFailure def test_no_space_before_blocktag(self): """ TODO: Bug in html2creole.strip_html(): Don't add a space before/after block tags """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" **foo** * one - """, """ + """, + """ <b>foo</b> <ul><li>one</li></ul> - """#, debug=True + """, # , debug=True ) @unittest.expectedFailure def test_escape_char(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" ~#1 http://domain.tld/~bar/ ~http://domain.tld/ [[Link]] ~[[Link]] - """, """ + """, + """ <p>#1<br /> <a href="http://domain.tld/~bar/">http://domain.tld/~bar/</a><br /> http://domain.tld/<br /> <a href="Link">Link</a><br /> [[Link]]</p> - """) + """, + ) @unittest.expectedFailure def test_images(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" a {{/image.jpg|JPG pictures}} and a {{/image.jpeg|JPEG pictures}} and a {{/image.gif|GIF pictures}} and a {{/image.png|PNG pictures}} ! picture [[www.domain.tld|{{foo.JPG|Foo}}]] as a link - """, """ + """, + """ <p>a <img src="/image.jpg" alt="JPG pictures"> and<br /> a <img src="/image.jpeg" alt="JPEG pictures"> and<br /> a <img src="/image.gif" alt="GIF pictures" /> and<br /> a <img src="/image.png" alt="PNG pictures" /> !</p> <p>picture <a href="www.domain.tld"><img src="foo.JPG" alt="Foo"></a> as a link</p> - """#, debug=True + """, # , debug=True ) - - diff --git a/creole/tests/test_cli.py b/creole/tests/test_cli.py index 5be41d5..806e689 100644 --- a/creole/tests/test_cli.py +++ b/creole/tests/test_cli.py @@ -9,17 +9,16 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + +import os import subprocess -import unittest import sys -import os import tempfile +import unittest -from creole import cmdline +from creole import VERSION_STRING, cmdline from creole.tests.utils.base_unittest import BaseCreoleTest -from creole import VERSION_STRING from creole.tests.utils.unittest_subprocess import SubprocessMixin CMDS = ("creole2html", "html2creole", "html2rest", "html2textile") @@ -28,34 +27,24 @@ CMDS = ("creole2html", "html2creole", "html2rest", "html2textile") class CliTestMixins(object): def test_creole2html(self): self._test_convert( - source_content=b"= test creole2html =", - dest_content="<h1>test creole2html</h1>", - cli_str="creole2html", + source_content=b"= test creole2html =", dest_content="<h1>test creole2html</h1>", cli_str="creole2html", ) def test_html2creole(self): self._test_convert( - source_content=b"<h1>test html2creole</h1>", - dest_content="= test html2creole", - cli_str="html2creole", + source_content=b"<h1>test html2creole</h1>", dest_content="= test html2creole", cli_str="html2creole", ) def test_html2rest(self): self._test_convert( source_content=b"<h1>test html2rest</h1>", - dest_content=( - "==============\n" - "test html2rest\n" - "==============" - ), + dest_content=("==============\n" "test html2rest\n" "=============="), cli_str="html2rest", ) def test_html2textile(self): self._test_convert( - source_content=b"<h1>test html2textile</h1>", - dest_content="h1. test html2textile", - cli_str="html2textile", + source_content=b"<h1>test html2textile</h1>", dest_content="h1. test html2textile", cli_str="html2textile", ) @@ -71,19 +60,14 @@ class CreoleCLITests(BaseCreoleTest, SubprocessMixin, CliTestMixins): dest_file = tempfile.NamedTemporaryFile() destfilepath = dest_file.name - stdout=( - "Convert '%(src)s' to '%(dst)s' with %(prog)s (codec: utf-8)\n" - "done. '%(dst)s' created." - ) % { + stdout = ("Convert '%(src)s' to '%(dst)s' with %(prog)s (codec: utf-8)\n" "done. '%(dst)s' created.") % { "prog": cli_str, "src": sourcefilepath, "dst": destfilepath, } self.assertSubprocess( - popen_args=[cli_str, sourcefilepath, destfilepath], - retcode=0, stdout=stdout, - verbose=False, + popen_args=[cli_str, sourcefilepath, destfilepath], retcode=0, stdout=stdout, verbose=False, ) dest_file.seek(0) @@ -94,20 +78,13 @@ class CreoleCLITests(BaseCreoleTest, SubprocessMixin, CliTestMixins): def test_version(self): for cmd in CMDS: - version_info = "%s from python-creole v%s" % ( - cmd, VERSION_STRING - ) + version_info = f"{cmd} from python-creole v{VERSION_STRING}" self.assertSubprocess( - popen_args=[cmd, "--version"], - retcode=0, - stdout=version_info, - verbose=False, + popen_args=[cmd, "--version"], retcode=0, stdout=version_info, verbose=False, ) - class CreoleCLITestsDirect(BaseCreoleTest, CliTestMixins): - def setUp(self): super(CreoleCLITestsDirect, self).setUp() self._old_sys_argv = sys.argv[:] @@ -127,7 +104,7 @@ class CreoleCLITestsDirect(BaseCreoleTest, CliTestMixins): destfilepath = dest_file.name sys.argv = [cli_str, sourcefilepath, destfilepath] - cli = getattr(cmdline, "cli_%s" % cli_str) + cli = getattr(cmdline, f"cli_{cli_str}") cli() dest_file.seek(0) @@ -137,5 +114,5 @@ class CreoleCLITestsDirect(BaseCreoleTest, CliTestMixins): self.assertEqual(result_content, dest_content) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_creole2html.py b/creole/tests/test_creole2html.py index 4e21e13..f54dde5 100644 --- a/creole/tests/test_creole2html.py +++ b/creole/tests/test_creole2html.py @@ -16,36 +16,35 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import sys import unittest import warnings -try: - from StringIO import StringIO -except ImportError: - from io import StringIO # python 3 +from creole import creole2html + +from creole.shared import example_macros +from creole.shared.utils import dict2string, string2dict +from creole.tests import test_macros +from creole.tests.utils.base_unittest import BaseCreoleTest + + +from io import StringIO try: from pygments import highlight + PYGMENTS = True except ImportError: PYGMENTS = False -from creole.tests.utils.base_unittest import BaseCreoleTest -from creole.tests import test_macros -from creole.py3compat import PY3 - -from creole import creole2html -from creole.shared import example_macros -from creole.shared.utils import string2dict, dict2string - class TestCreole2html(BaseCreoleTest): """ Tests around creole2html API and macro function. """ + def setUp(self): # For fallback tests example_macros.PYGMENTS = PYGMENTS @@ -57,10 +56,7 @@ class TestCreole2html(BaseCreoleTest): my_stderr = StringIO() creole2html( markup_string="<<notexist1>><<notexist2>><</notexist2>>", - emitter_kwargs={ - "verbose":2, - "stderr":my_stderr, - } + emitter_kwargs={"verbose": 2, "stderr": my_stderr,}, ) error_msg = my_stderr.getvalue() @@ -69,14 +65,16 @@ class TestCreole2html(BaseCreoleTest): # Check if we get a traceback information into our stderr handler must_have = ( - "Traceback", "'notexist1'", "'notexist2'", + "Traceback", + "'notexist1'", + "'notexist2'", ) for part in must_have: - tb_lines = [" -"*40] + tb_lines = [" -" * 40] tb_lines += error_msg.splitlines() - tb_lines += [" -"*40] + tb_lines += [" -" * 40] tb = "\n".join([" >>> %s" % l for l in tb_lines]) - msg = "%r not found in:\n%s" % (part, tb) + msg = f"{part!r} not found in:\n{tb}" # TODO: use assertIn if python 2.6 will be not support anymore. if part not in error_msg: raise self.failureException(msg) @@ -87,89 +85,68 @@ class TestCreole2html(BaseCreoleTest): """ html = creole2html( markup_string="<<html>><p>foo</p><</html>><bar?>", - emitter_kwargs={ - "verbose":1, - "macros":example_macros, - "stderr":sys.stderr, - } + emitter_kwargs={"verbose": 1, "macros": example_macros, "stderr": sys.stderr,}, ) - self.assertEqual(html, '<p>foo</p>\n<p><bar?></p>') + self.assertEqual(html, "<p>foo</p>\n<p><bar?></p>") def test_example_macros2(self): html = creole2html( markup_string="<<html>>{{{<nocode>}}}<</html>>", - emitter_kwargs={ - "verbose":1, - "macros":example_macros, - "stderr":sys.stderr, - } + emitter_kwargs={"verbose": 1, "macros": example_macros, "stderr": sys.stderr,}, ) - self.assertEqual(html, '{{{<nocode>}}}') + self.assertEqual(html, "{{{<nocode>}}}") def test_example_macros3(self): html = creole2html( markup_string="<<html>>1<</html>><<html>>2<</html>>", - emitter_kwargs={ - "verbose":1, - "macros":example_macros, - "stderr":sys.stderr, - } + emitter_kwargs={"verbose": 1, "macros": example_macros, "stderr": sys.stderr,}, ) - self.assertEqual(html, '1\n2') + self.assertEqual(html, "1\n2") def test_macro_dict(self): """ simple test for the "macro API" """ + def test(text, foo, bar): return "|".join([foo, bar, text]) html = creole2html( markup_string="<<test bar='b' foo='a'>>c<</test>>", - emitter_kwargs={ - "verbose":1, - "macros":{"test":test}, - "stderr":sys.stderr, - } + emitter_kwargs={"verbose": 1, "macros": {"test": test}, "stderr": sys.stderr,}, ) - self.assertEqual(html, 'a|b|c') + self.assertEqual(html, "a|b|c") def test_macro_callable(self): """ simple test for the "macro API" """ + def testmacro(): pass - self.assertRaises(TypeError, + self.assertRaises( + TypeError, creole2html, markup_string="<<test no=1 arg2='foo'>>bar<</test>>", - emitter_kwargs={ - "verbose":1, - "macros":testmacro, - "stderr":sys.stderr, - } + emitter_kwargs={"verbose": 1, "macros": testmacro, "stderr": sys.stderr,}, ) def test_macro_wrong_arguments_with_error_report(self): """ simple test for the "macro API" """ + def test(text, foo): pass + my_stderr = StringIO() html = creole2html( markup_string="<<test bar='foo'>>c<</test>>", - emitter_kwargs={ - "verbose":2, - "macros":{"test":test}, - "stderr":my_stderr, - } - ) - self.assertEqual(html, - "[Error: Macro 'test' error: test() got an unexpected keyword argument 'bar']" + emitter_kwargs={"verbose": 2, "macros": {"test": test}, "stderr": my_stderr,}, ) + self.assertEqual(html, "[Error: Macro 'test' error: test() got an unexpected keyword argument 'bar']") error_msg = my_stderr.getvalue() # Check traceback information into our stderr handler @@ -181,26 +158,21 @@ class TestCreole2html(BaseCreoleTest): for part in must_have: self.assertIn(part, error_msg) - def test_macro_wrong_arguments_quite(self): """ simple test for the "macro API" """ + def test(text, foo): pass + my_stderr = StringIO() html = creole2html( markup_string="<<test bar='foo'>>c<</test>>", - emitter_kwargs={ - "verbose":1, - "macros":{"test":test}, - "stderr":my_stderr, - } - ) - self.assertEqual(html, - "[Error: Macro 'test' error: test() got an unexpected keyword argument 'bar']" + emitter_kwargs={"verbose": 1, "macros": {"test": test}, "stderr": my_stderr,}, ) + self.assertEqual(html, "[Error: Macro 'test' error: test() got an unexpected keyword argument 'bar']") error_msg = my_stderr.getvalue() self.assertEqual(error_msg, "") @@ -212,19 +184,21 @@ class TestCreole2html(BaseCreoleTest): # due to https://bitbucket.org/birkenfeld/pygments-main/issues/1254/empty-at-the-begining-of-the-highlight # an empty <span></span> is now part of pygments output - self.assert_creole2html(r""" + self.assert_creole2html( + r""" Here a simple code macro test: <<code ext=".py">> for i in xrange(10): print('hello world') <</code>> - """, """ + """, + """ <p>Here a simple code macro test:</p> <div class="pygments"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span><br /> <span class="k">print</span><span class="p">(</span><span class="s1">'hello world'</span><span class="p">)</span><br /> </pre></div><br /> """, - macros={'code': example_macros.code} + macros={"code": example_macros.code}, ) def test_code_macro_fallback(self): @@ -238,12 +212,13 @@ class TestCreole2html(BaseCreoleTest): for i in xrange(10): print('hello world') <</code>> - """, """ + """, + """ <p>Here a simple code macro test:</p> <pre>for i in xrange(10): print('hello world')</pre> """, - macros={'code': example_macros.code} + macros={"code": example_macros.code}, ) def test_code_macro_fallback_escape(self): @@ -255,17 +230,15 @@ class TestCreole2html(BaseCreoleTest): <<code ext=".py">> print('This >>should<< be escaped!') <</code>> - """, """ + """, + """ <pre>print('This >>should<< be escaped!')</pre> """, - macros={'code': example_macros.code} + macros={"code": example_macros.code}, ) - - class TestCreole2htmlMarkup(BaseCreoleTest): - def test_creole_basic(self): out_string = creole2html("a text line.") self.assertEqual(out_string, "<p>a text line.</p>") @@ -281,68 +254,81 @@ class TestCreole2htmlMarkup(BaseCreoleTest): out_string = creole2html("first\r\nsecond") self.assertEqual(out_string, "<p>first<br />\nsecond</p>") - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def test_creole_linebreak(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" Force\\linebreak - """, """ + """, + """ <p>Force<br /> linebreak</p> - """) + """, + ) def test_html_lines(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" This is a normal Text block witch would escape html chars like < and > ;) So you can't insert <html> directly. <p>This escaped, too.</p> - """, """ + """, + """ <p>This is a normal Text block witch would<br /> escape html chars like < and > ;)</p> <p>So you can't insert <html> directly.</p> <p><p>This escaped, too.</p></p> - """) + """, + ) def test_escape_char(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" ~#1 http://domain.tld/~bar/ ~http://domain.tld/ [[Link]] ~[[Link]] - """, """ + """, + """ <p>#1<br /> <a href="http://domain.tld/~bar/">http://domain.tld/~bar/</a><br /> http://domain.tld/<br /> <a href="Link">Link</a><br /> [[Link]]</p> - """) + """, + ) def test_cross_paragraphs(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" Bold and italics should //not be... ...able// to **cross paragraphs.** - """, """ + """, + """ <p>Bold and italics should //not be...</p> <p>...able// to **cross</p> <p>paragraphs.**</p> - """) + """, + ) def test_list_special(self): """ optional whitespace before the list """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" * Item 1 ** Item 1.1 ** Item 1.2 @@ -351,7 +337,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): # one ## two - """, """ + """, + """ <ul> <li>Item 1 <ul> @@ -367,13 +354,15 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <li>two</li> </ol></li> </ol> - """) + """, + ) def test_macro_basic(self): """ Test the three different macro types with a "unittest macro" """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" There exist three different macro types: A <<unittest_macro1 args="foo1">>bar1<</unittest_macro1>> in a line... ...a single <<unittest_macro1 foo="bar">> tag, @@ -385,7 +374,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): text <</unittest_macro2>> the end - """, r""" + """, + r""" <p>There exist three different macro types:<br /> A [test macro1 - kwargs: args="foo1",text="bar1"] in a line...<br /> ...a single [test macro1 - kwargs: foo="bar",text=null] tag,<br /> @@ -399,14 +389,16 @@ class TestCreole2htmlMarkup(BaseCreoleTest): ) def test_macro_html1(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" html macro: <<html>> <p><<this is broken 'html', but it will be pass throu>></p> <</html>> inline: <<html>>{...}<</html>> code - """, r""" + """, + r""" <p>html macro:</p> <p><<this is broken 'html', but it will be pass throu>></p> @@ -443,18 +435,20 @@ class TestCreole2htmlMarkup(BaseCreoleTest): self.assert_creole2html(source_string, should_string, verbose=1) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Test with verbose=2 ans a StringIO stderr handler def test_wrong_macro_syntax(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" wrong macro line: <<summary>Some funky page summary.<</summary>> - """, r""" + """, + r""" <p>wrong macro line:<br /> [Error: Wrong macro arguments: ">Some funky page summary.<</summary" for macro 'summary' (maybe wrong macro tag syntax?)] </p> - """, # verbose=True + """, # verbose=True ) def test_macro_not_exist2(self): @@ -463,7 +457,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): No error messages should be inserted. """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" macro block: <<notexists>> foo bar @@ -471,31 +466,36 @@ class TestCreole2htmlMarkup(BaseCreoleTest): inline macro: <<notexisttoo foo="bar">> - """, r""" + """, + r""" <p>macro block:</p> <p>inline macro:<br /> </p> - """, verbose=False + """, + verbose=False, ) - def test_toc_simple(self): """ Simple test to check the table of content is correctly generated. """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" <<toc>> = Headline - """, """ + """, + """ <ul> <li><a href="#Headline">Headline</a></li> </ul> <a name="Headline"><h1>Headline</h1></a> - """) + """, + ) def test_toc_more_headlines(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" Between text and toc must be a newline. <<toc>> @@ -505,7 +505,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): = Headline 2 == Sub-Headline 2.1 == Sub-Headline 2.2 - """, """ + """, + """ <p>Between text and toc must be a newline.</p> <ul> @@ -526,17 +527,20 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <a name="Headline 2"><h1>Headline 2</h1></a> <a name="Sub-Headline 2.1"><h2>Sub-Headline 2.1</h2></a> <a name="Sub-Headline 2.2"><h2>Sub-Headline 2.2</h2></a> - """) + """, + ) def test_toc_chaotic_headlines(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" <<toc>> = level 1 === level 3 == level 2 ==== level 4 = level 1 - """, """ + """, + """ <ul> <li><a href="#level 1">level 1</a></li> <ul> @@ -557,10 +561,12 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <a name="level 2"><h2>level 2</h2></a> <a name="level 4"><h4>level 4</h4></a> <a name="level 1"><h1>level 1</h1></a> - """) + """, + ) def test_toc_depth_1(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" <<toc depth=1>> = Headline 1 == Sub-Headline 1.1 @@ -571,7 +577,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): == Sub-Headline 2.1 == Sub-Headline 2.2 === Sub-Sub-Headline 2.2.1 - """, """ + """, + """ <ul> <li><a href="#Headline 1">Headline 1</a></li> <li><a href="#Headline 2">Headline 2</a></li> @@ -585,10 +592,12 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <a name="Sub-Headline 2.1"><h2>Sub-Headline 2.1</h2></a> <a name="Sub-Headline 2.2"><h2>Sub-Headline 2.2</h2></a> <a name="Sub-Sub-Headline 2.2.1"><h3>Sub-Sub-Headline 2.2.1</h3></a> - """) + """, + ) def test_toc_depth_2(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" <<toc depth=2>> = Headline 1 == Sub-Headline 1.1 @@ -599,7 +608,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): == Sub-Headline 2.1 == Sub-Headline 2.2 === Sub-Sub-Headline 2.2.1 - """, """ + """, + """ <ul> <li><a href="#Headline 1">Headline 1</a></li> <ul> @@ -621,10 +631,12 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <a name="Sub-Headline 2.1"><h2>Sub-Headline 2.1</h2></a> <a name="Sub-Headline 2.2"><h2>Sub-Headline 2.2</h2></a> <a name="Sub-Sub-Headline 2.2.1"><h3>Sub-Sub-Headline 2.2.1</h3></a> - """) + """, + ) def test_toc_depth_3(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" <<toc depth=3>> = Headline 1 == Sub-Headline 1.1 @@ -635,7 +647,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): == Sub-Headline 2.1 == Sub-Headline 2.2 === Sub-Sub-Headline 2.2.1 - """, """ + """, + """ <ul> <li><a href="#Headline 1">Headline 1</a></li> <ul> @@ -664,23 +677,28 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <a name="Sub-Headline 2.1"><h2>Sub-Headline 2.1</h2></a> <a name="Sub-Headline 2.2"><h2>Sub-Headline 2.2</h2></a> <a name="Sub-Sub-Headline 2.2.1"><h3>Sub-Sub-Headline 2.2.1</h3></a> - """) + """, + ) def test_toc_with_no_toc(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" <<toc>> = This is the Headline Use {{{<<toc>>}}} to insert a table of contents. - """, """ + """, + """ <ul> <li><a href="#This is the Headline">This is the Headline</a></li> </ul> <a name="This is the Headline"><h1>This is the Headline</h1></a> <p>Use <tt><<toc>></tt> to insert a table of contents.</p> - """) + """, + ) def test_toc_more_then_one_toc(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" Not here: {{{ print("<<toc>>") @@ -694,7 +712,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <<toc>> = Headline == Sub-Headline - """, """ + """, + """ <p>Not here:</p> <pre> print("<<toc>>") @@ -713,17 +732,20 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <<toc>></p> <a name="Headline"><h1>Headline</h1></a> <a name="Sub-Headline"><h2>Sub-Headline</h2></a> - """) + """, + ) def test_toc_headline_before_toc(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" = headline == sub headline <<toc>> ok? - """, """ + """, + """ <a name="headline"><h1>headline</h1></a> <a name="sub headline"><h2>sub headline</h2></a> @@ -735,115 +757,149 @@ class TestCreole2htmlMarkup(BaseCreoleTest): </ul> <p>ok?</p> - """) + """, + ) def test_image(self): """ test image tag with different picture text """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" {{foobar1.jpg}} {{/path1/path2/foobar2.jpg}} {{/path1/path2/foobar3.jpg|foobar3.jpg}} - """, """ + """, + """ <p><img src="foobar1.jpg" title="foobar1.jpg" alt="foobar1.jpg" /><br /> <img src="/path1/path2/foobar2.jpg" title="/path1/path2/foobar2.jpg" alt="/path1/path2/foobar2.jpg" /><br /> <img src="/path1/path2/foobar3.jpg" title="foobar3.jpg" alt="foobar3.jpg" /></p> - """) + """, + ) def test_image_with_size(self): """ test image tag with size dimention (good and bad) """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" {{/path1/path2/foobar3.jpg|foo|160x90}} {{/path1/path2/foobar3.jpg|foo| 160 x 90 }} {{/path1/path2/foobar3.jpg|foo|160}} {{/path1/path2/foobar3.jpg||160x90}} {{/path1/path2/foobar3.jpg|foo|}} - """, """ + """, + """ <p><img src="/path1/path2/foobar3.jpg" title="foo" alt="foo" width="160" height="90" /><br /> <img src="/path1/path2/foobar3.jpg" title="foo" alt="foo" width="160" height="90" /><br /> <img src="/path1/path2/foobar3.jpg" title="foo|160" alt="foo|160" /><br /> <img src="/path1/path2/foobar3.jpg" title="/path1/path2/foobar3.jpg" alt="/path1/path2/foobar3.jpg" width="160" height="90" /><br /> <img src="/path1/path2/foobar3.jpg" title="foo|" alt="foo|" /></p> - """) + """, + ) def test_image_with_size_strict(self): """ test image tag with size dimention (good and bad) """ - self.assert_creole2html(r""" + self.assert_creole2html( + r""" {{/path1/path2/foobar3.jpg|foo|160x90}} {{/path1/path2/foobar3.jpg|foo|160}} - """, """ + """, + """ <p><img src="/path1/path2/foobar3.jpg" title="foo|160x90" alt="foo|160x90" /><br /> <img src="/path1/path2/foobar3.jpg" title="foo|160" alt="foo|160" /></p> - """, strict=True) + """, + strict=True, + ) def test_image_unknown_extension(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" # {{/path/to/image.ext|image ext}} one # {{/no/extension|no extension}} two # {{/image.xyz}} tree - """, """ + """, + """ <ol> <li><img src="/path/to/image.ext" title="image ext" alt="image ext" /> one</li> <li><img src="/no/extension" title="no extension" alt="no extension" /> two</li> <li><img src="/image.xyz" title="/image.xyz" alt="/image.xyz" /> tree</li> </ol> - """) + """, + ) def test_links(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" [[/foobar/Creole_(Markup)]] [[http://de.wikipedia.org/wiki/Creole_(Markup)|Creole@wikipedia]] - """, """ + """, + """ <p><a href="/foobar/Creole_(Markup)">/foobar/Creole_(Markup)</a><br /> <a href="http://de.wikipedia.org/wiki/Creole_(Markup)">Creole@wikipedia</a></p> - """) + """, + ) def test_standalone_hyperlink(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" a link to the http://www.pylucid.org page. - """, """ - <p>a link to the <a href="http://www.pylucid.org">http://www.pylucid.org</a> page.</p> + """, """ + <p>a link to the <a href="http://www.pylucid.org">http://www.pylucid.org</a> page.</p> + """, ) def test_wiki_style_line_breaks1(self): html = creole2html( - markup_string=self._prepare_text(""" + markup_string=self._prepare_text( + """ wiki style linebreaks ...and not blog styled. - """), - parser_kwargs={"blog_line_breaks":False}, + """ + ), + parser_kwargs={"blog_line_breaks": False}, ) - self.assertEqual(html, self._prepare_text(""" + self.assertEqual( + html, + self._prepare_text( + """ <p>wiki style linebreaks</p> <p>...and not blog styled.</p> - """)) + """ + ), + ) def test_wiki_style_line_breaks2(self): html = creole2html( - markup_string=self._prepare_text(""" + markup_string=self._prepare_text( + """ **one** //two// * one * two - """), - parser_kwargs={"blog_line_breaks":False}, + """ + ), + parser_kwargs={"blog_line_breaks": False}, ) - self.assertEqual(html, self._prepare_text(""" + self.assertEqual( + html, + self._prepare_text( + """ <p><strong>one</strong> <i>two</i></p> <ul> \t<li>one</li> \t<li>two</li> </ul> - """)) + """ + ), + ) def test_wiki_style_line_breaks3(self): html = creole2html( - markup_string=self._prepare_text(""" + markup_string=self._prepare_text( + """ with blog line breaks, every line break would be convertet into<br /> with wiki style not. @@ -856,10 +912,14 @@ class TestCreole2htmlMarkup(BaseCreoleTest): block 2 end - """), - parser_kwargs={"blog_line_breaks":False}, + """ + ), + parser_kwargs={"blog_line_breaks": False}, ) - self.assertEqual(html, self._prepare_text(""" + self.assertEqual( + html, + self._prepare_text( + """ <p>with blog line breaks, every line break would be convertet into<br /> with wiki style not.</p> <p>This is the first line,<br /> @@ -870,114 +930,127 @@ class TestCreole2htmlMarkup(BaseCreoleTest): <p>new line block 2</p> <p>end</p> - """)) - + """ + ), + ) def test_headline_spaces(self): """ https://code.google.com/p/python-creole/issues/detail?id=15 """ html = creole2html(markup_string="== Headline1 == \n== Headline2== ") - self.assertEqual(html, self._prepare_text(""" + self.assertEqual( + html, + self._prepare_text( + """ <h2>Headline1</h2> <h2>Headline2</h2> - """)) + """ + ), + ) def test_tt(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" inline {{{<escaped>}}} and {{{ **not strong** }}}... ...and ##**strong** Teletyper## ;) - """, """ + """, + """ <p>inline <tt><escaped></tt> and <tt> **not strong** </tt>...<br /> ...and <tt><strong>strong</strong> Teletyper</tt> ;)</p> - """) + """, + ) def test_protocol_in_brackets(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" My Server ([[ftp://foo/bar]]) is ok. - """, """ + """, + """ <p>My Server (<a href="ftp://foo/bar">ftp://foo/bar</a>) is ok.</p> - """) - self.assert_creole2html(r""" + """, + ) + self.assert_creole2html( + r""" My Server (ftp://foo/bar) is ok. - """, """ + """, + """ <p>My Server (ftp://foo/bar) is ok.</p> - """) + """, + ) def test_protocol_with_brackets(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" A http://en.wikipedia.org/wiki/Uri_(Island) link. - """, """ + """, + """ <p>A <a href="http://en.wikipedia.org/wiki/Uri_(Island)">http://en.wikipedia.org/wiki/Uri_(Island)</a> link.</p> - """) + """, + ) def test_wrong_protocol(self): - self.assert_creole2html(r""" + self.assert_creole2html( + r""" ~ftp://ok - """, """ + """, + """ <p>ftp://ok</p> - """) - self.assert_creole2html(r""" + """, + ) + self.assert_creole2html( + r""" ftp: - """, """ + """, + """ <p>ftp:</p> - """) - self.assert_creole2html(r""" + """, + ) + self.assert_creole2html( + r""" ftp:/ - """, """ + """, + """ <p>ftp:/</p> - """) - self.assert_creole2html(r""" + """, + ) + self.assert_creole2html( + r""" missing space.ftp://ok - """, """ + """, + """ <p>missing space.ftp://ok</p> - """) + """, + ) class TestStr2Dict(unittest.TestCase): def test_basic(self): - self.assertEqual( - string2dict('key1="value1" key2="value2"'), - {'key2': 'value2', 'key1': 'value1'} - ) + self.assertEqual(string2dict('key1="value1" key2="value2"'), {"key2": "value2", "key1": "value1"}) def test_bool(self): - self.assertEqual( - string2dict('unicode=True'), - {'unicode': True} - ) + self.assertEqual(string2dict("unicode=True"), {"unicode": True}) def test_mixed1(self): self.assertEqual( string2dict('A="B" C=1 D=1.1 E=True F=False G=None'), - {'A': 'B', 'C': 1, 'E': True, 'D': '1.1', 'G': None, 'F': False} + {"A": "B", "C": 1, "E": True, "D": "1.1", "G": None, "F": False}, ) def test_mixed2(self): - self.assertEqual( - string2dict('''key1="'1'" key2='"2"' key3="""'3'""" '''), - {'key3': 3, 'key2': 2, 'key1': 1} - ) + self.assertEqual(string2dict('''key1="'1'" key2='"2"' key3="""'3'""" '''), {"key3": 3, "key2": 2, "key1": 1}) + class TestDict2String(unittest.TestCase): def test_basic(self): - self.assertEqual( - dict2string({'key':'value'}), - 'key="value"' - ) + self.assertEqual(dict2string({"key": "value"}), 'key="value"') def test_basic2(self): - self.assertEqual( - dict2string({'foo':"bar", "no":123}), - 'foo="bar" no=123' - ) + self.assertEqual(dict2string({"foo": "bar", "no": 123}), 'foo="bar" no=123') + def test_basic3(self): - self.assertEqual( - dict2string({"foo":'bar', "no":"ABC"}), - 'foo="bar" no="ABC"' - ) + self.assertEqual(dict2string({"foo": "bar", "no": "ABC"}), 'foo="bar" no="ABC"') + -if __name__ == '__main__': - unittest.main( - verbosity=2 - ) +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/creole/tests/test_cross_compare_all.py b/creole/tests/test_cross_compare_all.py index 58259d1..04a782d 100644 --- a/creole/tests/test_cross_compare_all.py +++ b/creole/tests/test_cross_compare_all.py @@ -18,11 +18,9 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals - -import unittest +import unittest from creole.tests.utils.base_unittest import BaseCreoleTest @@ -32,6 +30,7 @@ class CrossCompareTests(BaseCreoleTest): Cross compare tests for creol2html _and_ html2creole with the same test strings. Used BaseCreoleTest.assertCreole() """ + def test_bold_italics(self): self.cross_compare( creole_string=r""" @@ -137,7 +136,7 @@ class CrossCompareTests(BaseCreoleTest): <h5>Section Title 5</h5> <h6>Section Title 6</h6> - """ + """, ) self.cross_compare( rest_string=""" @@ -168,7 +167,7 @@ class CrossCompareTests(BaseCreoleTest): <h4>Section Title 4</h4> <h5>Section Title 5</h5> <h6>Section Title 6</h6> - """ + """, ) def test_horizontal_rule(self): @@ -188,7 +187,7 @@ class CrossCompareTests(BaseCreoleTest): <hr /> <p>Text after the line.</p> - """ + """, ) self.cross_compare( rest_string=all_markups, @@ -196,7 +195,7 @@ class CrossCompareTests(BaseCreoleTest): <p>Text before horizontal rule.</p> <hr /> <p>Text after the line.</p> - """ + """, ) def test_link(self): @@ -212,7 +211,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>X <a href="http://domain.tld">link B</a> test.</p> - """ + """, ) def test_link_without_title(self): @@ -228,7 +227,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p><a href="http://www.pylucid.org">http://www.pylucid.org</a></p> - """ + """, ) def test_link_with_unknown_protocol(self): @@ -245,7 +244,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>X <a href="foo://bar">unknown protocol</a> Y</p> - """ + """, ) def test_link_with_at_sign(self): @@ -255,7 +254,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>X <a href="http://de.wikipedia.org/wiki/Creole_(Markup)">Creole@wikipedia</a></p> - """ + """, ) self.cross_compare( rest_string=""" @@ -263,7 +262,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>X <a href="http://de.wikipedia.org/wiki/Creole_(Markup)">Creole@wikipedia</a></p> - """ + """, ) self.cross_compare_textile( textile_string=""" @@ -271,7 +270,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>X <a href="http://domain.tld">foo@domain</a></p> - """ + """, ) def test_image(self): @@ -289,7 +288,7 @@ class CrossCompareTests(BaseCreoleTest): a <img src="/image.gif" title="GIF pictures" alt="GIF pictures" /> and<br /> a <img src="/image.png" title="PNG pictures" alt="PNG pictures" /> !<br /> <img src="/path1/path2/image" title="Image without files ext?" alt="Image without files ext?" /></p> - """ + """, ) self.cross_compare( textile_string=""" @@ -309,7 +308,7 @@ class CrossCompareTests(BaseCreoleTest): a <img alt="PNG pictures" src="/image.png" title="PNG pictures" /> !<br /> <img alt="Image without files ext?" src="/path1/path2/image" title="Image without files ext?" /></p> - """ + """, ) self.cross_compare( rest_string=""" @@ -339,7 +338,7 @@ class CrossCompareTests(BaseCreoleTest): <p>3 <img alt="GIF pictures" src="/image.gif" /> tree</p> <p>4 <img alt="PNG pictures" src="/image.png" /> four</p> <p>5 <img alt="Image without files ext?" src="/path1/path2/image" /> five</p> - """ + """, ) def test_link_image(self): @@ -350,7 +349,7 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>Linked <a href="http://example.com/"><img src="myimage.jpg" title="example site" alt="example site" /> image</a></p> - """ + """, ) self.cross_compare( textile_string=""" @@ -358,21 +357,20 @@ class CrossCompareTests(BaseCreoleTest): """, html_string=""" <p>Linked <a href="http://example.com/"><img alt="example site" src="myimage.jpg" title="example site" /> image</a></p> - """ + """, ) - -# self.cross_compare(# FIXME: ReSt -# rest_string=""" -# I recommend you try |PyLucid CMS|_. -# -# .. |PyLucid CMS| image:: /images/pylucid.png -# .. _PyLucid CMS: http://www.pylucid.org/ -# """, -# html_string=""" -# <p>I recommend you try <a href="http://www.pylucid.org/"><img alt="PyLucid CMS" src="/images/pylucid.png" /></a>.</p> -# """ -# ) + # self.cross_compare(# FIXME: ReSt + # rest_string=""" + # I recommend you try |PyLucid CMS|_. + # + # .. |PyLucid CMS| image:: /images/pylucid.png + # .. _PyLucid CMS: http://www.pylucid.org/ + # """, + # html_string=""" + # <p>I recommend you try <a href="http://www.pylucid.org/"><img alt="PyLucid CMS" src="/images/pylucid.png" /></a>.</p> + # """ + # ) def test_pre1(self): self.cross_compare( @@ -390,8 +388,9 @@ class CrossCompareTests(BaseCreoleTest): <pre> * no list </pre> - """) - self.cross_compare(# FIXME: Not the best html2rest output + """, + ) + self.cross_compare( # FIXME: Not the best html2rest output rest_string=""" Preformatting text: @@ -411,40 +410,39 @@ class CrossCompareTests(BaseCreoleTest): text... end. </pre> <p>Under pre block</p> - """ + """, ) - -# def test_pre2(self): -# """ TODO: html2creole: wrong lineendings """ -# self.cross_compare( -# creole_string=r""" -# start -# -# {{{ -# * no list -# }}} -# -# end -# """, -# textile_string=""" -# start -# -# <pre> -# * no list -# </pre> -# -# end -# """, -# html_string=""" -# <p>start</p> -# -# <pre> -# * no list -# </pre> -# -# <p>end</p> -# """) + # def test_pre2(self): + # """ TODO: html2creole: wrong lineendings """ + # self.cross_compare( + # creole_string=r""" + # start + # + # {{{ + # * no list + # }}} + # + # end + # """, + # textile_string=""" + # start + # + # <pre> + # * no list + # </pre> + # + # end + # """, + # html_string=""" + # <p>start</p> + # + # <pre> + # * no list + # </pre> + # + # <p>end</p> + # """) def test_pre_contains_braces(self): self.cross_compare( @@ -487,7 +485,8 @@ class CrossCompareTests(BaseCreoleTest): x[i]--; }}} </pre> - """) + """, + ) def test_list(self): """ Bold, Italics, Links, Pre in Lists """ @@ -513,7 +512,7 @@ class CrossCompareTests(BaseCreoleTest): <li>item about a <a href="/foo/bar">certain_page</a></li> </ol> """, - strip_lines=True + strip_lines=True, ) def test_simple_table(self): @@ -567,5 +566,5 @@ class CrossCompareTests(BaseCreoleTest): ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_cross_compare_creole.py b/creole/tests/test_cross_compare_creole.py index 6431fc0..831a647 100644 --- a/creole/tests/test_cross_compare_creole.py +++ b/creole/tests/test_cross_compare_creole.py @@ -4,7 +4,7 @@ """ cross compare creole unittest ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - + Compare all similarities between: * creole2html * html2creole @@ -16,7 +16,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest @@ -33,13 +33,13 @@ class CrossCompareCreoleTests(BaseCreoleTest): **//bold italics//** //**bold italics**// //This is **also** good.// - + Creole 1.0 optional: This is ##monospace## text. This is ^^superscripted^^ text. This is ,,subscripted,, text. This is __underlined__ text. - + own additions: This is --small-- and this ~~strikeout~~ ;) """, @@ -48,16 +48,16 @@ class CrossCompareCreoleTests(BaseCreoleTest): <strong><i>bold italics</i></strong><br /> <i><strong>bold italics</strong></i><br /> <i>This is <strong>also</strong> good.</i></p> - + <p>Creole 1.0 optional:<br /> This is <tt>monospace</tt> text.<br /> This is <sup>superscripted</sup> text.<br /> This is <sub>subscripted</sub> text.<br /> This is <u>underlined</u> text.</p> - + <p>own additions:<br /> This is <small>small</small> and this <del>strikeout</del> ;)</p> - """ + """, ) def test_cross_lines_html2creole(self): @@ -65,16 +65,18 @@ class CrossCompareCreoleTests(BaseCreoleTest): see: http://code.google.com/p/python-creole/issues/detail?id=13 TODO: The way back creole2html doesn't work, see below """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" Bold and italics should //be able// to **cross lines.** - """, """ + """, + """ <p>Bold and italics should <i>be<br /> able</i> to <strong>cross<br /> lines.</strong></p> - """) - + """, + ) def test_small(self): """ @@ -99,7 +101,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): no ,, subscripted<br /> no __ underline</p> """, - debug=False + debug=False, ) def test_link(self): @@ -111,19 +113,22 @@ class CrossCompareCreoleTests(BaseCreoleTest): html_string=""" <p>this is <a href="/a internal">/a internal</a> link.<br /> 1 <a href="internal links">link A</a> test.</p> - """ + """, ) def test_bolditalic_links(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" //[[a internal]]// **[[Shortcut2|a page2]]** //**[[Shortcut3|a page3]]**// - """, """ + """, + """ <p><i><a href="a internal">a internal</a></i><br /> <strong><a href="Shortcut2">a page2</a></strong><br /> <i><strong><a href="Shortcut3">a page3</a></strong></i></p> - """) + """, + ) def test_pre_contains_braces(self): """ @@ -132,7 +137,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): self.cross_compare_creole( creole_string=r""" === Closing braces in nowiki: - + {{{ if (x != NULL) { for (i = 0; i < size; i++) { @@ -143,7 +148,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): """, html_string=""" <h3>Closing braces in nowiki:</h3> - + <pre> if (x != NULL) { for (i = 0; i < size; i++) { @@ -151,105 +156,118 @@ class CrossCompareCreoleTests(BaseCreoleTest): x[i]--; }}} </pre> - """) + """, + ) def test_pre2(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" 111 - + {{{ //This// does **not** get [[formatted]] }}} 222 one - + {{{ foo bar }}} two - """, """ + """, + """ <p>111</p> - + <pre> //This// does **not** get [[formatted]] </pre> <p>222</p> - + <p>one</p> - + <pre> foo bar </pre> <p>two</p> - """) + """, + ) def test_pre(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" start - + {{{ * no list <html escaped> }}} end - """, """ + """, + """ <p>start</p> - + <pre> * no list <html escaped> </pre> <p>end</p> - """) + """, + ) def test_tt(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" this is ##**strong** Teletyper## ;) - """, """ + """, + """ <p>this is <tt><strong>strong</strong> Teletyper</tt> ;)</p> - """) - + """, + ) def test_no_inline_headline(self): self.cross_compare_creole( creole_string=r""" = Headline - + === **not** //parsed// - + No == headline == or? """, html_string=""" <h1>Headline</h1> - + <h3>**not** //parsed//</h3> - + <p>No == headline == or?</p> - """ + """, ) def test_horizontal_rule(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" one ---- two - """, """ + """, + """ <p>one</p> <hr /> <p>two</p> - """) + """, + ) def test_bullet_list(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" * Item 1 ** Item 1.1 ** a **bold** Item 1.2 @@ -267,7 +285,8 @@ class CrossCompareCreoleTests(BaseCreoleTest): *** 3 **** 4 ***** 5 - """, """ + """, + """ <ul> <li>Item 1 <ul> @@ -303,10 +322,12 @@ class CrossCompareCreoleTests(BaseCreoleTest): </ul></li> </ul></li> </ul> - """) + """, + ) def test_number_list(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" # Item 1 ## Item 1.1 ## a **bold** Item 1.2 @@ -324,7 +345,8 @@ class CrossCompareCreoleTests(BaseCreoleTest): ### 3 #### 4 ##### 5 - """, """ + """, + """ <ol> <li>Item 1 <ol> @@ -361,11 +383,12 @@ class CrossCompareCreoleTests(BaseCreoleTest): </ol></li> </ol> """, -# debug = True + # debug = True ) def test_big_table(self): - self.cross_compare_creole(r""" + self.cross_compare_creole( + r""" A Table... |= Headline |= a other\\headline |= the **big end** | @@ -374,7 +397,8 @@ class CrossCompareCreoleTests(BaseCreoleTest): | link test: | a [[/url/|link]] in | a cell. | | | | empty cells | ...end - """, """ + """, + """ <p>A Table...</p> <table> @@ -408,7 +432,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): </table> <p>...end</p> """, -# debug = True + # debug = True ) def test_html_macro_unknown_nodes(self): @@ -417,12 +441,14 @@ class CrossCompareCreoleTests(BaseCreoleTest): Note: All cross compare tests use html2creole.HTML_MACRO_UNKNOWN_NODES """ - self.cross_compare_creole(""" + self.cross_compare_creole( + """ 111 <<html>><x><</html>>foo<<html>></x><</html>> 222 333<<html>><x foo1="bar1"><</html>>foobar<<html>></x><</html>>444 555<<html>><x /><</html>>666 - """, """ + """, + """ <p>111 <x>foo</x> 222<br /> 333<x foo1="bar1">foobar</x>444</p> @@ -435,13 +461,17 @@ class CrossCompareCreoleTests(BaseCreoleTest): ) def test_entities(self): - self.cross_compare_creole(""" + self.cross_compare_creole( + """ less-than sign: < greater-than sign: > - """, """ + """, + """ <p>less-than sign: <<br /> greater-than sign: ></p> - """) + """, + ) + # def test_macro_html1(self): # self.cross_compare_creole(r""" @@ -471,7 +501,6 @@ class CrossCompareCreoleTests(BaseCreoleTest): # """) - # def test_macro_pygments_code(self): # self.cross_compare_creole(r""" # a macro: @@ -498,7 +527,5 @@ class CrossCompareCreoleTests(BaseCreoleTest): # """) - - -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_cross_compare_rest.py b/creole/tests/test_cross_compare_rest.py index c40e924..e0e1339 100644 --- a/creole/tests/test_cross_compare_rest.py +++ b/creole/tests/test_cross_compare_rest.py @@ -13,7 +13,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest @@ -32,7 +32,7 @@ class CrossCompareReStTests(BaseCreoleTest): <p>less-than sign: <</p> <p>greater-than sign: ></p> """, -# debug=True + # debug=True ) def test_bullet_lists_basic(self): @@ -51,7 +51,7 @@ class CrossCompareReStTests(BaseCreoleTest): <li>item 3</li> </ul> """, -# debug=True + # debug=True ) def test_numbered_lists(self): @@ -81,7 +81,7 @@ class CrossCompareReStTests(BaseCreoleTest): </li> </ol> """, -# debug=True + # debug=True ) def test_bullet_lists_nested(self): @@ -133,7 +133,7 @@ class CrossCompareReStTests(BaseCreoleTest): </ul> <p>Text under list.</p> """, -# debug=True + # debug=True ) def test_typeface_basic(self): @@ -146,7 +146,7 @@ class CrossCompareReStTests(BaseCreoleTest): """, html_string=""" <p><em>emphasis</em> <strong>strong</strong></p> - """ + """, ) def test_substitution_image_with_alt(self): @@ -161,7 +161,7 @@ class CrossCompareReStTests(BaseCreoleTest): html_string=""" <p>A inline <img alt="substitution text" src="/url/to/image.png" /> image.</p> <p>...and some text below.</p> - """ + """, ) def test_table(self): @@ -185,7 +185,7 @@ class CrossCompareReStTests(BaseCreoleTest): </tr> </table> <p>After table.</p> - """ + """, ) def test_link_in_table1(self): @@ -205,7 +205,7 @@ class CrossCompareReStTests(BaseCreoleTest): <tr><td><a href="foo/bar">table item</a></td> </tr> </table> - """ + """, ) def test_link_in_table2(self): @@ -225,7 +225,7 @@ class CrossCompareReStTests(BaseCreoleTest): <tr><td>foo <a href="foo/bar">table item</a> bar</td> </tr> </table> - """ + """, ) def test_link_in_table3(self): @@ -256,7 +256,7 @@ class CrossCompareReStTests(BaseCreoleTest): </td> </tr> </table> - """ + """, ) def test_paragraph_bwlow_table_links(self): @@ -285,7 +285,7 @@ class CrossCompareReStTests(BaseCreoleTest): </table> <p>Text after table.</p> """, -# debug=True + # debug=True ) def test_reuse_link_substitution1(self): @@ -313,7 +313,7 @@ class CrossCompareReStTests(BaseCreoleTest): </table> <p>Text after table.</p> """, -# debug=True + # debug=True ) def test_reuse_link_substitution2(self): @@ -337,7 +337,7 @@ class CrossCompareReStTests(BaseCreoleTest): </table> <p>and here <a href="foo/bar/">foo bar</a> again, after table.</p> """, -# debug=True + # debug=True ) def test_reuse_image_substitution(self): @@ -362,7 +362,7 @@ class CrossCompareReStTests(BaseCreoleTest): </tr> </table> """, -# debug=True + # debug=True ) def test_duplicate_image_substitution(self): @@ -391,12 +391,10 @@ class CrossCompareReStTests(BaseCreoleTest): </table> <p>again: the <img alt="same" src="/image.png" /> image and <a href="/url/foo/">same</a> link!</p> """, -# debug=True + # debug=True ) - - # def test_inline_literal(self): # """ TODO # http://docutils.sourceforge.net/docs/user/rst/quickref.html#inline-markup @@ -424,7 +422,7 @@ class CrossCompareReStTests(BaseCreoleTest): # """) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main( -# defaultTest="CrossCompareReStTests.test_paragraph_bwlow_table_links", + # defaultTest="CrossCompareReStTests.test_paragraph_bwlow_table_links", ) diff --git a/creole/tests/test_cross_compare_textile.py b/creole/tests/test_cross_compare_textile.py index 2a0681a..7a60944 100644 --- a/creole/tests/test_cross_compare_textile.py +++ b/creole/tests/test_cross_compare_textile.py @@ -16,7 +16,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest @@ -61,7 +61,7 @@ class CrossCompareTextileTests(BaseCreoleTest): <span>span</span><br /> <code>code</code></p> - """ + """, ) def test_escape_in_pre(self): @@ -75,8 +75,9 @@ class CrossCompareTextileTests(BaseCreoleTest): <pre> <html escaped> </pre> - """) + """, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_html2creole.py b/creole/tests/test_html2creole.py index 58a20ef..0296540 100644 --- a/creole/tests/test_html2creole.py +++ b/creole/tests/test_html2creole.py @@ -5,87 +5,90 @@ """ html2creole tests ~~~~~~~~~~~~~~~~~ - + special html to creole convert tests, witch can't tests in "cross compare" - + :copyleft: 2008-2011 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import unittest -from creole.tests.utils.base_unittest import BaseCreoleTest +import unittest from creole import html2creole -from creole.shared.unknown_tags import raise_unknown_node, use_html_macro, \ - escape_unknown_nodes, transparent_unknown_nodes +from creole.shared.unknown_tags import ( + escape_unknown_nodes, + raise_unknown_node, + transparent_unknown_nodes, + use_html_macro, +) +from creole.tests.utils.base_unittest import BaseCreoleTest class TestHtml2Creole(unittest.TestCase): """ Tests around html2creole API. """ - pass - + pass class TestHtml2CreoleMarkup(BaseCreoleTest): -# def assertCreole(self, raw_markup, raw_html, debug=False, **kwargs): -# self.assert_html2creole(raw_markup, raw_html, debug=debug, **kwargs) + # def assertCreole(self, raw_markup, raw_html, debug=False, **kwargs): + # self.assert_html2creole(raw_markup, raw_html, debug=debug, **kwargs) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def test_not_used(self): """ Some other html tags -> convert. """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" **Bold text** **Big text** //em tag// //italic// - """, """ + """, + """ <p><b>Bold text</b><br /> <big>Big text</big><br /> <em>em tag</em><br /> <i>italic</i></p> - """) + """, + ) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def test_raise_unknown_node(self): """ Test creole.html2creole.raise_unknown_node callable: Raise NotImplementedError on unknown tags. """ - self.assertRaises(NotImplementedError, - html2creole, - html_string="<unknwon>", - unknown_emit=raise_unknown_node - ) + self.assertRaises(NotImplementedError, html2creole, html_string="<unknwon>", unknown_emit=raise_unknown_node) def test_use_html_macro(self): """ Test creole.html2creole.use_html_macro callable: Use the <<html>> macro to mask unknown tags. """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" 111 <<html>><unknown><</html>>foo<<html>></unknown><</html>> 222 333<<html>><unknown foo1="bar1" foo2="bar2"><</html>>foobar<<html>></unknown><</html>>444 555<<html>><unknown /><</html>>666 - """, """ + """, + """ <p>111 <unknown>foo</unknown> 222<br /> 333<unknown foo1="bar1" foo2="bar2">foobar</unknown>444</p> <p>555<unknown />666</p> """, - unknown_emit=use_html_macro + unknown_emit=use_html_macro, ) def test_escape_unknown_nodes(self): @@ -93,18 +96,20 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): Test creole.html2creole.escape_unknown_nodes callable: All unknown tags should be escaped. """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" 111 <unknown>foo</unknown> 222 333<unknown foo1="bar1" foo2="bar2">foobar</unknown>444 555<unknown />666 - """, """ + """, + """ <p>111 <unknown>foo</unknown> 222<br /> 333<unknown foo1="bar1" foo2="bar2">foobar</unknown>444</p> <p>555<unknown />666</p> """, - unknown_emit=escape_unknown_nodes + unknown_emit=escape_unknown_nodes, ) def test_escape_unknown_nodes2(self): @@ -112,14 +117,16 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): HTMLParser has problems with <script> tags. See: http://bugs.python.org/issue670664 """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" <script>var js_sha_link='<p>***</p>';</script> - """, """ + """, + """ <script> var js_sha_link='<p>***</p>'; </script> """, - unknown_emit=escape_unknown_nodes + unknown_emit=escape_unknown_nodes, ) def test_transparent_unknown_nodes(self): @@ -128,42 +135,51 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): All unknown tags should be "transparent" and show only their child nodes' content. """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" //baz//, **quux** - """, """ + """, + """ <form class="foo" id="bar"><label><em>baz</em></label>, <strong>quux</strong></form> - """, unknown_emit=transparent_unknown_nodes + """, + unknown_emit=transparent_unknown_nodes, ) def test_transparent_unknown_nodes2(self): - """ + """ HTMLParser has problems with <script> tags. See: http://bugs.python.org/issue670664 """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" FOO var a='<em>STRONG</em>'; BAR - """, """ + """, + """ <p>FOO <script>var a='<em>STRONG</em>';</script> BAR</p> - """, unknown_emit=transparent_unknown_nodes + """, + unknown_emit=transparent_unknown_nodes, ) def test_transparent_unknown_nodes_block_elements(self): """ Test that block elements insert linefeeds into the stream. """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" //baz//, **quux** spam, ham, and eggs - """, """ + """, + """ <div><em>baz</em>,</div> <fieldset><strong>quux</strong></fieldset> <span>spam, </span><label>ham, </label>and eggs - """, unknown_emit=transparent_unknown_nodes + """, + unknown_emit=transparent_unknown_nodes, ) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def test_entities(self): """ @@ -174,13 +190,15 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): Box Drawing: http://pylucid.org/_command/144/DecodeUnicode/display/66/ """ - self.assert_html2creole(""" + self.assert_html2creole( + """ * less-than sign: < < < * greater-than sign: > > > * copyright sign: © © * box drawing: ╬ ╬ * german umlauts: ä ö ü - """, """ + """, + """ <ul> <li>less-than sign: < < <</li> <li>greater-than sign: > > ></li> @@ -188,47 +206,62 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): <li>box drawing: ╬ ╬</li> <li>german umlauts: ä ö ü</li> </ul> - """) + """, + ) def test_html_entity_nbsp(self): """ Non breaking spaces is not in htmlentitydefs """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" a non braking space: [ ] ! - """, """ + """, + """ <p>a non braking space: [ ] !</p> - """) + """, + ) def test_html_entity_in_pre(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" {{{<code>{% lucidTag RSS url="http url" %}</code>}}} - """, """ + """, + """ <pre><code>{% lucidTag RSS url="http url" %}</code></pre> - """) + """, + ) def test_unknown_entity(self): """ Test a unknown html entity. FIXME: What sould happend? """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" copy&paste - """, """ + """, + """ <p>copy&paste</p> - """) - self.assert_html2creole(r""" + """, + ) + self.assert_html2creole( + r""" [[/url/|Search & Destroy]] - """, """ + """, + """ <a href="/url/">Search & Destroy</a> - """) + """, + ) def test_tbody_table(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" Ignore 'tbody' tag in tables: - + |= Headline 1 |= Headline 2 | | cell one | cell two | end - """, """ + """, + """ <p>Ignore 'tbody' tag in tables:</p> <table> <tbody> @@ -243,31 +276,37 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): </tbody> </table> <p>end</p> - """) + """, + ) def test_p_table(self): """ strip <p> tags in table cells """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" | cell one | cell two\\new line | - """, """ + """, + """ <table> <tr> <td><p>cell one</p></td> <td><p>cell two</p><p>new line</p><p></p></td> </tr> </table> - """) + """, + ) def test_image(self): """ test image tag with different alt/title attribute """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" {{foobar1.jpg|foobar1.jpg}} {{/foobar2.jpg|foobar2.jpg}} {{/path1/path2/foobar3.jpg|foobar3.jpg}} {{/foobar4.jpg|It's foobar 4}} {{/foobar5.jpg|It's foobar 5}} {{/foobar6.jpg|a long picture title}} - """, """ + """, + """ <p><img src="foobar1.jpg" /><br /> <img src="/foobar2.jpg" /><br /> <img src="/path1/path2/foobar3.jpg" /><br /> @@ -277,71 +316,92 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO 9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="data uri should be disallowed" /></p> - """) + """, + ) def test_image_with_size(self): """ test image tag with sizes """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" {{foobar1.jpg|foobar1.jpg}} {{foobar2.jpg|foobar2.jpg|90x160}} {{foobar3.jpg|foobar3.jpg}} - """, """ + """, + """ <p><img src="foobar1.jpg" /><br /> <img src="foobar2.jpg" width="160" height="90" /><br /> <img src="foobar3.jpg" width="160" /></p> - """) + """, + ) def test_image_with_size_strict(self): """ test image tag with sizes """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" {{foobar1.jpg|foobar1.jpg}} {{foobar2.jpg|foobar2.jpg}} {{foobar3.jpg|foobar3.jpg}} - """, """ + """, + """ <p><img src="foobar1.jpg" /><br /> <img src="foobar2.jpg" width="160" height="90" /><br /> <img src="foobar3.jpg" width="160" /></p> - """, strict=True) + """, + strict=True, + ) def test_non_closed_br(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" one two - """, """ + """, + """ <p>one<br> two</p> - """) + """, + ) def test_explicit_closed_br(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" one two - """, """ + """, + """ <p>one<br></br> two</p> - """) + """, + ) def test_newline_before_list(self): """ http://code.google.com/p/python-creole/issues/detail?id=16 """ - self.assert_html2creole(r""" + self.assert_html2creole( + r""" **foo** - + * one - """, """ + """, + """ <b>foo</b><ul><li>one</li></ul> - """) + """, + ) def test_empty_tags_are_not_escaped(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" //baz//, **quux** - """, """ + """, + """ <div class="foo" id="bar"><span><em>baz</em></span>, <strong>quux</strong></div> - """) + """, + ) def test_nested_listsitems_with_paragraph(self): - self.assert_html2creole(""" + self.assert_html2creole( + """ * item 1 ** subitem 1.1 *** subsubitem 1.1.1 @@ -349,7 +409,8 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): ** subitem 1.2 * item 2 ** subitem 2.1 - """, """ + """, + """ <ul> <li><p>item 1</p> <ul> @@ -368,56 +429,72 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): </ul> </li> </ul> - """) + """, + ) def test_class_in_list(self): """https://code.google.com/p/python-creole/issues/detail?id=19#c4""" - self.assert_html2creole(r""" + self.assert_html2creole( + r""" # foo - """, """ + """, + """ <ol class=gbtc><li>foo</li></ol> - """)#, debug=True) + """, + ) # , debug=True) def test_ignore_links_without_href(self): """https://code.google.com/p/python-creole/issues/detail?id=19#c4""" - self.assert_html2creole(r""" + self.assert_html2creole( + r""" bar - """, """ + """, + """ <a class="foo">bar</a> - """)#, debug=True) + """, + ) # , debug=True) def test_newlines_after_headlines(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" = Headline news [[http://google.com|The googlezor]] is a big bad mother. - """, """ + """, + """ <h1>Headline news</h1> <p><a href="http://google.com">The googlezor</a> is a big bad mother.</p> - """) + """, + ) def test_links(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" test link: '[[internal links|link A]]' 1 and test link: '[[http://domain.tld|link B]]' 2. - """, """ + """, + """ <p>test link: '<a href="internal links">link A</a>' 1 and<br /> test link: '<a href="http://domain.tld">link B</a>' 2.</p> - """) + """, + ) def test_horizontal_rule(self): - self.assert_html2creole(r""" + self.assert_html2creole( + r""" one - + ---- - + two - """, """ + """, + """ <p>one</p> <hr /> <p>two</p> - """) + """, + ) def test_nested_empty_tags(self): self.assert_html2creole2("TEST", "<p>TEST</p>") @@ -543,8 +620,7 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): # ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main( -# defaultTest="TestHtml2CreoleMarkup.test_nested_listsitems_with_paragraph" + # defaultTest="TestHtml2CreoleMarkup.test_nested_listsitems_with_paragraph" ) - diff --git a/creole/tests/test_html2rest.py b/creole/tests/test_html2rest.py index 9056d54..f66a324 100644 --- a/creole/tests/test_html2rest.py +++ b/creole/tests/test_html2rest.py @@ -4,7 +4,7 @@ """ html2rest unittest ~~~~~~~~~~~~~~~~~~~~~ - + Unittests for special cases which only works in the html2rest way. Note: This only works fine if there is no problematic whitespace handling. @@ -13,7 +13,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest @@ -29,7 +29,7 @@ class ReStTests(BaseCreoleTest): self.assert_html2rest( rest_string=""" first block, line 1 and line 2 - + second block, line 1 and line 2 """, html_string=""" @@ -38,7 +38,7 @@ class ReStTests(BaseCreoleTest): <p>second block, line 1 and line 2</p> """, -# debug=True + # debug=True ) def test_substitution_image_without_alt_or_title(self): @@ -53,7 +53,7 @@ class ReStTests(BaseCreoleTest): html_string=""" <p>A inline <img src="/url/to/image.png" /> image.</p> <p>...and some text below.</p> - """ + """, ) def test_substitution_image_with_title(self): @@ -68,14 +68,14 @@ class ReStTests(BaseCreoleTest): html_string=""" <p>A inline <img title="foo bar" src="/url/to/image.png" /> image.</p> <p>...and some text below.</p> - """ + """, ) def test_pre_code1(self): self.assert_html2rest( rest_string=""" :: - + >>> from creole import creole2html >>> creole2html("This is **creole //markup//**") '<p>This is <strong>creole <i>markup</i></strong></p> @@ -86,7 +86,7 @@ class ReStTests(BaseCreoleTest): >>> creole2html("This is **creole //markup//**") '<p>This is <strong>creole <i>markup</i></strong></p>\n' </pre> - """ + """, ) def test_escape(self): @@ -98,7 +98,7 @@ class ReStTests(BaseCreoleTest): <ul> <li>Use <tt> when {{{ ... }}} is inline and not <pre>, or not?</li> </ul> - """ + """, ) def test_inline_literals(self): @@ -110,28 +110,28 @@ class ReStTests(BaseCreoleTest): <ul> <p>This text is an example of <tt>inline literals</tt>.</p> </ul> - """ + """, ) def test_list_without_p(self): self.assert_html2rest( rest_string=""" A nested bullet lists: - + * item 1 without p-tag - + * A **`subitem 1.1 </1.1/url/>`_ link** here. - + * subsubitem 1.1.1 - + * subsubitem 1.1.2 - + * subitem 1.2 - + * item 2 without p-tag - + * subitem 2.1 - + Text under list. """, html_string=""" @@ -155,7 +155,7 @@ class ReStTests(BaseCreoleTest): </li> </ul> <p>Text under list.</p> - """ + """, ) def test_table_with_headings(self): @@ -174,7 +174,7 @@ class ReStTests(BaseCreoleTest): <tr><td>item 1</td><td>item 2</td> </tr> </table> - """ + """, ) def test_table_without_headings(self): @@ -193,18 +193,20 @@ class ReStTests(BaseCreoleTest): <tr><td>item 3</td><td>item 4</td> </tr> </table> - """ + """, ) - + def test_duplicate_substitution1(self): - self.assertRaises(Html2restException, self.assert_html2rest, + self.assertRaises( + Html2restException, + self.assert_html2rest, rest_string=""" +-----------------------------+ | this is `same`_ first time. | +-----------------------------+ - + .. _same: /first/ - + the `same </other/>`_ link? """, html_string=""" @@ -214,19 +216,21 @@ class ReStTests(BaseCreoleTest): </table> <p>the <a href="/other/">same</a> link?</p> """, -# debug=True + # debug=True ) - + def test_duplicate_link_substitution(self): - self.assertRaises(Html2restException, self.assert_html2rest, -# self.cross_compare( + self.assertRaises( + Html2restException, + self.assert_html2rest, + # self.cross_compare( rest_string=""" +-----------------------------+ | this is `same`_ first time. | +-----------------------------+ - + .. _same: /first/ - + the `same </other/>`_ link? """, html_string=""" @@ -236,16 +240,18 @@ class ReStTests(BaseCreoleTest): </table> <p>the <a href="/other/">same</a> link?</p> """, -# debug=True + # debug=True ) def test_duplicate_image_substitution(self): - self.assertRaises(Html2restException, self.assert_html2rest, -# self.cross_compare( + self.assertRaises( + Html2restException, + self.assert_html2rest, + # self.cross_compare( rest_string=""" a |image|... and a other |image|! - + .. |image| image:: /image.png .. |image| image:: /other.png """, @@ -253,11 +259,10 @@ class ReStTests(BaseCreoleTest): <p>a <img src="/image.png" title="image" alt="image" />...<br /> and a other <img src="/other.png" title="image" alt="image" />!</p> """, -# debug=True + # debug=True ) - # def test_preformat_unknown_nodes(self): # """ # Put unknown tags in a <pre> area. @@ -266,13 +271,13 @@ class ReStTests(BaseCreoleTest): # rest_string=""" # 111 <<pre>><x><</pre>>foo<<pre>></x><</pre>> 222 # 333<<pre>><x foo1="bar1"><</pre>>foobar<<pre>></x><</pre>>444 -# +# # 555<<pre>><x /><</pre>>666 # """, # html_string=""" # <p>111 <x>foo</x> 222<br /> # 333<x foo1="bar1">foobar</x>444</p> -# +# # <p>555<x />666</p> # """, # emitter_kwargs={"unknown_emit":preformat_unknown_nodes} @@ -281,7 +286,7 @@ class ReStTests(BaseCreoleTest): # def test_transparent_unknown_nodes(self): # """ # transparent_unknown_nodes is the default unknown_emit: -# +# # Remove all unknown html tags and show only # their child nodes' content. # """ @@ -289,17 +294,17 @@ class ReStTests(BaseCreoleTest): # rest_string=""" # 111 <<pre>><x><</pre>>foo<<pre>></x><</pre>> 222 # 333<<pre>><x foo1="bar1"><</pre>>foobar<<pre>></x><</pre>>444 -# +# # 555<<pre>><x /><</pre>>666 # """, # html_string=""" # <p>111 <x>foo</x> 222<br /> # 333<x foo1="bar1">foobar</x>444</p> -# +# # <p>555<x />666</p> # """, # ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_html2textile.py b/creole/tests/test_html2textile.py index f02fced..243b3c6 100644 --- a/creole/tests/test_html2textile.py +++ b/creole/tests/test_html2textile.py @@ -4,7 +4,7 @@ """ html2textile unittest ~~~~~~~~~~~~~~~~~~~~~ - + Unittests for special cases which only works in the html2textile way. Note: This only works fine if there is no problematic whitespace handling. @@ -13,7 +13,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest @@ -35,7 +35,7 @@ class TextileTests(BaseCreoleTest): <p>less-than sign: <<br /> greater-than sign: ></p> """, -# debug=True + # debug=True ) def test_preformat_unknown_nodes(self): @@ -46,22 +46,22 @@ class TextileTests(BaseCreoleTest): textile_string=""" 111 <<pre>><x><</pre>>foo<<pre>></x><</pre>> 222 333<<pre>><x foo1="bar1"><</pre>>foobar<<pre>></x><</pre>>444 - + 555<<pre>><x /><</pre>>666 """, html_string=""" <p>111 <x>foo</x> 222<br /> 333<x foo1="bar1">foobar</x>444</p> - + <p>555<x />666</p> """, - emitter_kwargs={"unknown_emit":preformat_unknown_nodes} + emitter_kwargs={"unknown_emit": preformat_unknown_nodes}, ) def test_transparent_unknown_nodes(self): """ transparent_unknown_nodes is the default unknown_emit: - + Remove all unknown html tags and show only their child nodes' content. """ @@ -75,11 +75,11 @@ class TextileTests(BaseCreoleTest): html_string=""" <p>111 <x>foo</x> 222<br /> 333<x foo1="bar1">foobar</x>444</p> - + <p>555<x />666</p> """, ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_macros.py b/creole/tests/test_macros.py index a5194f9..41eb33f 100644 --- a/creole/tests/test_macros.py +++ b/creole/tests/test_macros.py @@ -4,31 +4,32 @@ """ Creole unittest macros ~~~~~~~~~~~~~~~~~~~~~~ - + Note: all mecro functions must return unicode! - + :copyleft: 2008-2011 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import json + def unittest_macro1(**kwargs): """ >>> unittest_macro1(foo="bar") '[test macro1 - kwargs: foo="bar"]' - + >>> unittest_macro1() '[test macro1 - kwargs: ]' - + >>> unittest_macro1(a=1,b=2) '[test macro1 - kwargs: a=1,b=2]' """ - kwargs = ','.join(['%s=%s' % (k, json.dumps(v)) for k, v in sorted(kwargs.items())]) - return "[test macro1 - kwargs: %s]" % kwargs + kwargs = ",".join(["%s=%s" % (k, json.dumps(v)) for k, v in sorted(kwargs.items())]) + return f"[test macro1 - kwargs: {kwargs}]" def unittest_macro2(char, text): @@ -38,6 +39,8 @@ def unittest_macro2(char, text): """ return char.join(text.split()) -if __name__ == '__main__': + +if __name__ == "__main__": import doctest - print(doctest.testmod())
\ No newline at end of file + + print(doctest.testmod()) diff --git a/creole/tests/test_rest2html.py b/creole/tests/test_rest2html.py index ea23be8..ff89b93 100644 --- a/creole/tests/test_rest2html.py +++ b/creole/tests/test_rest2html.py @@ -4,14 +4,14 @@ """ rest2html unittest ~~~~~~~~~~~~~~~~~~ - + Unittests for rest2html, see: creole/rest2html/clean_writer.py :copyleft: 2011-2012 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import tempfile import unittest @@ -21,29 +21,34 @@ from creole.tests.utils.base_unittest import BaseCreoleTest class ReSt2HtmlTests(BaseCreoleTest): def test_clean_link_table(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ :homepage: http://code.google.com/p/python-creole/ - + :sourcecode: http://github.com/jedie/python-creole - """, """ + """, + """ <table> <tr><th>homepage:</th><td><a href="http://code.google.com/p/python-creole/">http://code.google.com/p/python-creole/</a></td> </tr> <tr><th>sourcecode:</th><td><a href="http://github.com/jedie/python-creole">http://github.com/jedie/python-creole</a></td> </tr> </table> - """) + """, + ) def test_clean_table(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ +------------+------------+ | Headline 1 | Headline 2 | +============+============+ | cell one | cell two | +------------+------------+ - """, """ + """, + """ <table> <colgroup> <col width="50%" /> @@ -56,24 +61,27 @@ class ReSt2HtmlTests(BaseCreoleTest): <td>cell two</td> </tr> </table> - """) + """, + ) def test_clean_list(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ * item 1 - + * item 1.1 - + * item 1.2 - + * item 2 - + numbered list: - + #. item A - + #. item B - """, """ + """, + """ <ul> <li><p>item 1</p> <ul> @@ -89,30 +97,38 @@ class ReSt2HtmlTests(BaseCreoleTest): <li>item A</li> <li>item B</li> </ol> - """) + """, + ) def test_clean_headline(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ ====== head 1 ====== - + ------ head 2 ------ - """, """ + """, + """ <h1>head 1</h1> <h2>head 2</h2> - """) + """, + ) def test_include_disabled_by_default(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ Include should be disabled by default. - + .. include:: doesntexist.txt - """, """ + """, + """ <p>Include should be disabled by default.</p> - """, report_level=3) # Set log level to "error" to suppress the waring output + """, + report_level=3, + ) # Set log level to "error" to suppress the waring output def test_include_enabled(self): test_content = "Content from include file." @@ -120,60 +136,80 @@ class ReSt2HtmlTests(BaseCreoleTest): with tempfile.NamedTemporaryFile() as temp: temp.write(test_content) temp.flush() - self.assert_rest2html(""" + self.assert_rest2html( + """ Enable include and test it. - + .. include:: %s - """ % temp.name, """ + """ + % temp.name, + """ <p>Enable include and test it.</p> <p>Content from include file.</p> - """, file_insertion_enabled=True, input_encoding="utf-8") + """, + file_insertion_enabled=True, + input_encoding="utf-8", + ) def test_raw_disabled_by_default(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ Raw directive should be disabled by default. - + .. raw:: html <hr width=50 size=10> - """, """ + """, + """ <p>Raw directive should be disabled by default.</p> - """, report_level=3) # Set log level to "error" to suppress the waring output + """, + report_level=3, + ) # Set log level to "error" to suppress the waring output def test_raw_enabled(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ Now RAW is enabled. - + .. raw:: html <hr width=50 size=10> - """, """ + """, + """ <p>Now RAW is enabled.</p> <hr width=50 size=10> - """, raw_enabled=True) + """, + raw_enabled=True, + ) def test_preserve_image_alignment(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ Image alignment should be preserved. .. image:: foo.png :align: right - """, """ + """, + """ <p>Image alignment should be preserved.</p> <img alt="foo.png" src="foo.png" align="right" /> - """) + """, + ) def test_preserve_figure_alignment(self): - self.assert_rest2html(""" + self.assert_rest2html( + """ Image alignment should be preserved. .. figure:: bar.png :align: right - """, """ + """, + """ <p>Image alignment should be preserved.</p> <img alt="bar.png" src="bar.png" align="right" /> - """) + """, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_setup.py b/creole/tests/test_setup.py index 52524dc..9e63c8c 100644 --- a/creole/tests/test_setup.py +++ b/creole/tests/test_setup.py @@ -9,11 +9,11 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import unittest -import sys + import os +import sys +import unittest import creole from creole.tests.utils.unittest_subprocess import SubprocessMixin @@ -26,22 +26,12 @@ class TestSetup(unittest.TestCase, SubprocessMixin): def test_setup_path(self): if not os.path.isfile(self.setup_path): - self.fail("Can't find setup.py: %r doesn't exist" % self.setup_path) + self.fail(f"Can't find setup.py: {self.setup_path!r} doesn't exist") def test_version(self): self.assertSubprocess( popen_args=(sys.executable, self.setup_path, "--version"), retcode=0, stdout=creole.VERSION_STRING, - verbose=True + verbose=True, ) - - def test_nose_hint(self): - popen_args, retcode, stdout = self.subprocess( - popen_args=(sys.executable, self.setup_path, "test"), - verbose=False, - ) - self.assertIn("Please use 'nosetests'", stdout) - self.assertNotEqual(retcode, 0) - - diff --git a/creole/tests/test_setup_utils.py b/creole/tests/test_setup_utils.py index f7b2975..53778e0 100644 --- a/creole/tests/test_setup_utils.py +++ b/creole/tests/test_setup_utils.py @@ -11,24 +11,24 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import unittest + import os +import tempfile +import unittest import warnings +import creole +from creole.setup_utils import get_long_description +from creole.tests.utils.base_unittest import BaseCreoleTest + try: import docutils + DOCUTILS = True except ImportError: DOCUTILS = False -import creole -from creole.setup_utils import get_long_description -from creole.tests.utils.base_unittest import BaseCreoleTest -from creole.py3compat import BINARY_TYPE, PY3, TEXT_TYPE -import tempfile - CREOLE_PACKAGE_ROOT = os.path.abspath(os.path.join(os.path.dirname(creole.__file__), "..")) TEST_README_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -48,19 +48,17 @@ class SetupUtilsTests(BaseCreoleTest): def test_creole_package_path(self): self.assertTrue( os.path.isdir(CREOLE_PACKAGE_ROOT), - "CREOLE_PACKAGE_ROOT %r is not a existing direcotry!" % CREOLE_PACKAGE_ROOT + f"CREOLE_PACKAGE_ROOT {CREOLE_PACKAGE_ROOT!r} is not a existing direcotry!", ) filepath = os.path.join(CREOLE_PACKAGE_ROOT, "README.creole") - self.assertTrue( - os.path.isfile(filepath), - "README file %r not found!" % filepath - ) + self.assertTrue(os.path.isfile(filepath), f"README file {filepath!r} not found!") def test_get_long_description_without_raise_errors(self): long_description = get_long_description(CREOLE_PACKAGE_ROOT, raise_errors=False) self.assertIn("=====\nabout\n=====\n\n", long_description) # Test created ReSt code from creole.rest_tools.clean_writer import rest2html + html = rest2html(long_description) self.assertIn("<h1>about</h1>\n", html) @@ -107,7 +105,7 @@ class SetupUtilsTests(BaseCreoleTest): SystemExit: ReSt2html error: link scheme not allowed """ path, filename, fd = self._tempfile(b"[[foo://bar]]") -# print(get_long_description(path, filename, raise_errors=True)) + # print(get_long_description(path, filename, raise_errors=True)) try: self.assertRaises(SystemExit, get_long_description, path, filename, raise_errors=True) finally: @@ -116,7 +114,7 @@ class SetupUtilsTests(BaseCreoleTest): def test_wrong_path_without_raise_errors(self): self.assertEqual( get_long_description("wrong/path", raise_errors=False).replace("u'", "'"), - "[Error: [Errno 2] No such file or directory: 'wrong/path/README.creole']\n" + "[Error: [Errno 2] No such file or directory: 'wrong/path/README.creole']\n", ) def test_wrong_path_with_raise_errors(self): @@ -125,15 +123,11 @@ class SetupUtilsTests(BaseCreoleTest): def test_readme_encoding(self): long_description = get_long_description(TEST_README_DIR, filename=TEST_README_FILENAME, raise_errors=True) - if PY3: - self.assertTrue(isinstance(long_description, TEXT_TYPE)) - else: - self.assertTrue(isinstance(long_description, BINARY_TYPE)) + self.assertTrue(isinstance(long_description, str)) txt = "German Umlaute: ä ö ü ß Ä Ö Ü" - if not PY3: - txt = txt.encode("utf-8") self.assertIn(txt, long_description) -if __name__ == '__main__': + +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/test_subprocess.py b/creole/tests/test_subprocess.py index 6babded..3360821 100644 --- a/creole/tests/test_subprocess.py +++ b/creole/tests/test_subprocess.py @@ -8,11 +8,11 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals -import unittest -import sys + import os +import sys +import unittest from creole.tests.utils.unittest_subprocess import SubprocessMixin @@ -20,7 +20,7 @@ from creole.tests.utils.unittest_subprocess import SubprocessMixin class TestSubprocessMixin(unittest.TestCase, SubprocessMixin): def test_find_executable(self): filepath = self.find_executable("python") - if not hasattr(self, "assertRegex"): # New in version 3.1 + if not hasattr(self, "assertRegex"): # New in version 3.1 self.assertRegex = self.assertRegexpMatches self.assertRegex(filepath, ".*?python.*?") @@ -29,16 +29,13 @@ class TestSubprocessMixin(unittest.TestCase, SubprocessMixin): self.find_executable("doesn't exists!") def test_executable_with_path(self): - msg = "'%s' unexpectedly found in '%s'" % ( - os.sep, sys.executable - ) + msg = f"'{os.sep}' unexpectedly found in '{sys.executable}'" with self.assertRaisesRegexp(AssertionError, msg): self.find_executable(sys.executable) def test_subprocess(self): popen_args, retcode, stdout = self.subprocess( - popen_args=[sys.executable, "-c", "import sys;sys.stdout.write('to stdout')"], - verbose=False + popen_args=[sys.executable, "-c", "import sys;sys.stdout.write('to stdout')"], verbose=False ) self.assertEqual(stdout, "to stdout") self.assertEqual(retcode, 0) @@ -58,12 +55,6 @@ class TestSubprocessMixin(unittest.TestCase, SubprocessMixin): self.assertSubprocess( popen_args=(sys.executable, "-c", code), retcode=0, - stdout=( - "to stdout 1\n" - "to stderr 1\n" - "to stdout 2\n" - "to stderr 2\n" - ), - verbose=True + stdout=("to stdout 1\n" "to stderr 1\n" "to stdout 2\n" "to stderr 2\n"), + verbose=True, ) - diff --git a/creole/tests/test_utils.py b/creole/tests/test_utils.py index 2ad8d07..e13e5f6 100644 --- a/creole/tests/test_utils.py +++ b/creole/tests/test_utils.py @@ -9,19 +9,19 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest -from creole.tests.utils.utils import MarkupTest from creole.shared.markup_table import MarkupTable +from creole.tests.utils.utils import MarkupTest class UtilsTests(MarkupTest): def assertEqual2(self, first, second, msg=""): self.assertNotEqual(first, second, msg) -# first = self._prepare_text(first) + # first = self._prepare_text(first) second = self._prepare_text(second) self.assertEqual(first, second, msg) @@ -45,7 +45,7 @@ class UtilsTests(MarkupTest): |* head1 |* head2 | | 1.1. | 1.2. | | 2.1. | 2.2. | - """ + """, ) def test_markup_table_textile(self): @@ -67,7 +67,7 @@ class UtilsTests(MarkupTest): |_. head1|_. head2| |1.1.|1.2.| |2.1.|2.2.| - """ + """, ) def test_markup_table_rest(self): @@ -93,9 +93,9 @@ class UtilsTests(MarkupTest): +-------+-------+ | 2.1. | 2.2. | +-------+-------+ - """ + """, ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/creole/tests/utils/base_unittest.py b/creole/tests/utils/base_unittest.py index f9002fa..bffcf09 100644 --- a/creole/tests/utils/base_unittest.py +++ b/creole/tests/utils/base_unittest.py @@ -11,47 +11,44 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re import warnings -from creole.tests.utils.utils import MarkupTest -from creole.py3compat import TEXT_TYPE +from creole import creole2html, html2creole, html2rest, html2textile +from creole.exceptions import DocutilsImportError +from creole.tests.utils.utils import MarkupTest try: import textile except ImportError: test_textile = False warnings.warn( - "Markup error: The Python textile library isn't installed." - " Download: http://pypi.python.org/pypi/textile" + "Markup error: The Python textile library isn't installed." " Download: http://pypi.python.org/pypi/textile" ) else: test_textile = True -from creole.exceptions import DocutilsImportError -from creole import creole2html, html2creole, html2textile, html2rest - try: from creole.rest_tools.clean_writer import rest2html except DocutilsImportError as err: REST_INSTALLED = False - warnings.warn("Can't run all ReSt unittests: %s" % err) + warnings.warn(f"Can't run all ReSt unittests: {err}") else: REST_INSTALLED = True tabs2spaces_re = re.compile(r"^(\t*)(.*?)$", re.M) - def tabs2spaces(html): """ form reformating textile html code >>> tabs2spaces("\\t<p>one<br />\\n\\t\\ttwo<br />\\n\\t\\t\\ttree</p>") '<p>one<br />\\n two<br />\\n tree</p>' """ + def reformat_tabs(match): tabs = match.group(1) text = match.group(2) @@ -60,8 +57,9 @@ def tabs2spaces(html): if indent < 0: indent = 0 -# print(len(tabs), indent, repr(tabs), text) + # print(len(tabs), indent, repr(tabs), text) return " " * indent + text + return tabs2spaces_re.sub(reformat_tabs, html) @@ -70,17 +68,15 @@ def strip_html_lines(html, strip_lines=False): >>> strip_html_lines("\t<p>foo \\n\\n\t\t bar</p>", strip_lines=True) '<p>foo\\nbar</p>' """ - html = "\n".join( - [line.strip(" \t") for line in html.splitlines() if line] - ) + html = "\n".join([line.strip(" \t") for line in html.splitlines() if line]) return html - class BaseCreoleTest(MarkupTest): """ Basic unittest class for all python-creole unittest classes. """ + def _debug_text(self, msg, raw_text): text = raw_text.replace(" ", ".") text = text.replace("\n", "\\n\n") @@ -88,7 +84,7 @@ class BaseCreoleTest(MarkupTest): print print("_" * 79) - print(" Debug Text: %s" % msg) + print(f" Debug Text: {msg}") print(text) print("-" * 79) @@ -105,12 +101,20 @@ class BaseCreoleTest(MarkupTest): f(member, container, *args, **kwargs) def assert_creole2html( - self, raw_creole, raw_html, - strip_lines=False, debug=False, - parser_kwargs={}, emitter_kwargs={}, - block_rules=None, blog_line_breaks=True, macros=None, verbose=None, stderr=None, - strict=False, - ): + self, + raw_creole, + raw_html, + strip_lines=False, + debug=False, + parser_kwargs={}, + emitter_kwargs={}, + block_rules=None, + blog_line_breaks=True, + macros=None, + verbose=None, + stderr=None, + strict=False, + ): """ compare the generated html code from the markup string >creole_string< with the >html_string< reference. @@ -121,10 +125,10 @@ class BaseCreoleTest(MarkupTest): # prepare whitespace on test strings markup_string = self._prepare_text(raw_creole) - assert isinstance(markup_string, TEXT_TYPE) + assert isinstance(markup_string, str) html_string = self._prepare_text(raw_html) - assert isinstance(html_string, TEXT_TYPE) + assert isinstance(html_string, str) if strip_lines: html_string = strip_html_lines(html_string, strip_lines) if debug: @@ -132,9 +136,13 @@ class BaseCreoleTest(MarkupTest): # convert creole markup into html code out_string = creole2html( - markup_string, debug, - block_rules=block_rules, blog_line_breaks=blog_line_breaks, - macros=macros, verbose=verbose, stderr=stderr, + markup_string, + debug, + block_rules=block_rules, + blog_line_breaks=blog_line_breaks, + macros=macros, + verbose=verbose, + stderr=stderr, strict=strict, ) if debug: @@ -148,64 +156,73 @@ class BaseCreoleTest(MarkupTest): # compare self.assertEqual(out_string, html_string, msg="creole2html") - def assert_html2creole2(self, creole, html, - debug=False, - unknown_emit=None, - strict=False, - ): + def assert_html2creole2( + self, creole, html, debug=False, unknown_emit=None, strict=False, + ): # convert html code into creole markup - out_string = html2creole( - html, debug, unknown_emit=unknown_emit, strict=strict - ) + out_string = html2creole(html, debug, unknown_emit=unknown_emit, strict=strict) if debug: self._debug_text("assert_html2creole() html2creole", out_string) # compare self.assertEqual(out_string, creole, msg="html2creole") - def assert_html2creole(self, raw_creole, raw_html, \ - strip_lines=False, debug=False, - # OLD API: - parser_kwargs={}, emitter_kwargs={}, - # html2creole: - unknown_emit=None, - strict=False, - ): + def assert_html2creole( + self, + raw_creole, + raw_html, + strip_lines=False, + debug=False, + # OLD API: + parser_kwargs={}, + emitter_kwargs={}, + # html2creole: + unknown_emit=None, + strict=False, + ): """ Compare the genereted markup from the given >raw_html< html code, with the given >creole_string< reference string. """ self.assertEqual(parser_kwargs, {}, "parser_kwargs is deprecated!") self.assertEqual(emitter_kwargs, {}, "parser_kwargs is deprecated!") -# assert isinstance(raw_html, TEXT_TYPE) -# creole_string = unicode(creole_string, encoding="utf8") -# raw_html = unicode(raw_html, "utf8") + # assert isinstance(raw_html, str) + # creole_string = unicode(creole_string, encoding="utf8") + # raw_html = unicode(raw_html, "utf8") self.assertNotEqual(raw_creole, raw_html) # prepare whitespace on test strings creole = self._prepare_text(raw_creole) - assert isinstance(creole, TEXT_TYPE) + assert isinstance(creole, str) if debug: self._debug_text("assert_creole2html() markup", creole) html = self._prepare_text(raw_html) - assert isinstance(html, TEXT_TYPE) + assert isinstance(html, str) self.assert_html2creole2(creole, html, debug, unknown_emit, strict) - def cross_compare_creole(self, creole_string, html_string, - strip_lines=False, debug=False, - # creole2html old API: - creole_parser_kwargs={}, html_emitter_kwargs={}, - # html2creole old API: - html_parser_kwargs={}, creole_emitter_kwargs={}, - - # creole2html new API: - block_rules=None, blog_line_breaks=True, macros=None, stderr=None, - # html2creole: - unknown_emit=None - ): + def cross_compare_creole( + self, + creole_string, + html_string, + strip_lines=False, + debug=False, + # creole2html old API: + creole_parser_kwargs={}, + html_emitter_kwargs={}, + # html2creole old API: + html_parser_kwargs={}, + creole_emitter_kwargs={}, + # creole2html new API: + block_rules=None, + blog_line_breaks=True, + macros=None, + stderr=None, + # html2creole: + unknown_emit=None, + ): """ Cross compare with: * creole2html @@ -216,23 +233,28 @@ class BaseCreoleTest(MarkupTest): self.assertEqual(html_parser_kwargs, {}, "html_parser_kwargs is deprecated!") self.assertEqual(creole_emitter_kwargs, {}, "creole_emitter_kwargs is deprecated!") - assert isinstance(creole_string, TEXT_TYPE) - assert isinstance(html_string, TEXT_TYPE) + assert isinstance(creole_string, str) + assert isinstance(html_string, str) self.assertNotEqual(creole_string, html_string) self.assert_creole2html( - creole_string, html_string, strip_lines, debug, - block_rules=block_rules, blog_line_breaks=blog_line_breaks, - macros=macros, stderr=stderr, + creole_string, + html_string, + strip_lines, + debug, + block_rules=block_rules, + blog_line_breaks=blog_line_breaks, + macros=macros, + stderr=stderr, ) self.assert_html2creole( - creole_string, html_string, strip_lines, debug, - unknown_emit=unknown_emit, + creole_string, html_string, strip_lines, debug, unknown_emit=unknown_emit, ) - def assert_html2textile(self, textile_string, html_string, \ - strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={}): + def assert_html2textile( + self, textile_string, html_string, strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={} + ): """ Check html2textile """ @@ -255,21 +277,21 @@ class BaseCreoleTest(MarkupTest): return textile_string, html_string - def cross_compare_textile(self, textile_string, html_string, \ - strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={}): + def cross_compare_textile( + self, textile_string, html_string, strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={} + ): """ Checks: * html2textile * textile2html """ -# assert isinstance(textile_string, TEXT_TYPE) -# assert isinstance(html_string, TEXT_TYPE) + # assert isinstance(textile_string, str) + # assert isinstance(html_string, str) self.assertNotEqual(textile_string, html_string) # compare html -> textile textile_string, html_string = self.assert_html2textile( - textile_string, html_string, - strip_lines, debug, parser_kwargs, emitter_kwargs + textile_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs ) # compare textile -> html @@ -286,8 +308,9 @@ class BaseCreoleTest(MarkupTest): self.assertEqual(html_string, html, msg="textile2html") - def assert_html2rest(self, rest_string, html_string, \ - strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={}): + def assert_html2rest( + self, rest_string, html_string, strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={} + ): """ Check html to reStructuredText converter """ @@ -310,8 +333,9 @@ class BaseCreoleTest(MarkupTest): return rest_string, html_string - def assert_rest2html(self, rest_string, html_string, \ - strip_lines=False, debug=False, prepare_strings=True, **kwargs): + def assert_rest2html( + self, rest_string, html_string, strip_lines=False, debug=False, prepare_strings=True, **kwargs + ): # compare rest -> html if not REST_INSTALLED: @@ -330,37 +354,40 @@ class BaseCreoleTest(MarkupTest): print(html) html = html.strip() -# html = html.replace("<br />", "<br />\n") -# html = tabs2spaces(html) + # html = html.replace("<br />", "<br />\n") + # html = tabs2spaces(html) if strip_lines: html = strip_html_lines(html, strip_lines) self.assertEqual(html, html_string, msg="rest2html") - def cross_compare_rest(self, rest_string, html_string, \ - strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={}): -# assert isinstance(textile_string, TEXT_TYPE) -# assert isinstance(html_string, TEXT_TYPE) + def cross_compare_rest( + self, rest_string, html_string, strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={} + ): + # assert isinstance(textile_string, str) + # assert isinstance(html_string, str) self.assertNotEqual(rest_string, html_string) rest_string, html_string = self.assert_html2rest( - rest_string, html_string, - strip_lines, debug, parser_kwargs, emitter_kwargs + rest_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs ) # compare rest -> html self.assert_rest2html( - rest_string, html_string, - strip_lines=strip_lines, debug=debug, - prepare_strings=False, + rest_string, html_string, strip_lines=strip_lines, debug=debug, prepare_strings=False, ) - def cross_compare(self, - html_string, - creole_string=None, - textile_string=None, - rest_string=None, - strip_lines=False, debug=False, parser_kwargs={}, emitter_kwargs={}): + def cross_compare( + self, + html_string, + creole_string=None, + textile_string=None, + rest_string=None, + strip_lines=False, + debug=False, + parser_kwargs={}, + emitter_kwargs={}, + ): """ Cross compare with: * creole2html @@ -369,20 +396,16 @@ class BaseCreoleTest(MarkupTest): * html2ReSt """ if creole_string: - self.cross_compare_creole( - creole_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs - ) + self.cross_compare_creole(creole_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs) if textile_string: - self.cross_compare_textile( - textile_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs - ) + self.cross_compare_textile(textile_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs) if rest_string: - self.cross_compare_rest( - rest_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs - ) + self.cross_compare_rest(rest_string, html_string, strip_lines, debug, parser_kwargs, emitter_kwargs) -if __name__ == '__main__': + +if __name__ == "__main__": import doctest + print(doctest.testmod()) diff --git a/creole/tests/utils/unittest_subprocess.py b/creole/tests/utils/unittest_subprocess.py index bca3779..24e182a 100644 --- a/creole/tests/utils/unittest_subprocess.py +++ b/creole/tests/utils/unittest_subprocess.py @@ -8,7 +8,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import print_function, unicode_literals + import json import os @@ -18,7 +18,7 @@ import sys class SubprocessMixin(object): # call .../env/bin/python will not add the .../env/bin/ to the PATH - SEARCH_PATH=[os.path.dirname(sys.executable)] + os.environ.get("PATH", "").split(os.pathsep) + SEARCH_PATH = [os.path.dirname(sys.executable)] + os.environ.get("PATH", "").split(os.pathsep) def find_executable(self, program): self.assertNotIn(os.sep, program) @@ -26,7 +26,7 @@ class SubprocessMixin(object): filepath = os.path.join(path, program) if os.path.isfile(filepath): if not os.access(filepath, os.X_OK): - sys.stderr.write("File %r is not executable?!?\n" % filepath) + sys.stderr.write(f"File {filepath!r} is not executable?!?\n") else: return filepath @@ -39,21 +39,19 @@ class SubprocessMixin(object): print("Call:", popen_args) try: - process = subprocess.Popen(popen_args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True, + process = subprocess.Popen( + popen_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, ) except Exception as err: - self.fail("Error subprocess call with %r: %s" % (popen_args, err)) + self.fail(f"Error subprocess call with {popen_args!r}: {err}") stdout, stderr = process.communicate() retcode = process.poll() if verbose: - print("return code: %r" % retcode) - print("stdout: %r" % stdout) - print("stderr: %r" % stderr) + print(f"return code: {retcode!r}") + print(f"stdout: {stdout!r}") + print(f"stderr: {stderr!r}") stdout = stdout.strip() return popen_args, retcode, stdout @@ -72,11 +70,5 @@ class SubprocessMixin(object): " ---------- [stdout] ---------- \n" "%s\n" "-------------------------------" - ) % ( - err, - repr(popen_args2), retcode2, - stdout2, - ) + ) % (err, repr(popen_args2), retcode2, stdout2,) self.fail(msg) - - diff --git a/creole/tests/utils/utils.py b/creole/tests/utils/utils.py index 5e2b24a..2309f49 100644 --- a/creole/tests/utils/utils.py +++ b/creole/tests/utils/utils.py @@ -11,18 +11,17 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import difflib import textwrap import unittest - ## error output format: # =1 -> via repr() # =2 -> raw VERBOSE = 1 -#VERBOSE = 2 +# VERBOSE = 2 def make_diff(block1, block2): @@ -41,38 +40,39 @@ class MarkupTest(unittest.TestCase): """ Special error class: Try to display markup errors in a better way. """ + def _format_output(self, txt): txt = txt.split("\\n") if VERBOSE == 1: - txt = "".join(['%s\\n\n' % i for i in txt]) + txt = "".join(["%s\\n\n" % i for i in txt]) elif VERBOSE == 2: - txt = "".join(['%s\n' % i for i in txt]) + txt = "".join(["%s\n" % i for i in txt]) return txt def assertEqual(self, first, second, msg=""): if not first == second: if VERBOSE >= 2: - print("first: %r" % first) - print("second: %r" % second) + print(f"first: {first!r}") + print(f"second: {second!r}") - #~ first = first.rstrip("\\n") - #~ second = second.rstrip("\\n") + # ~ first = first.rstrip("\\n") + # ~ second = second.rstrip("\\n") try: diff = make_diff(first, second) except AttributeError: - raise self.failureException("%s is not %s" % (repr(first), repr(second))) + raise self.failureException(f"{repr(first)} is not {repr(second)}") if VERBOSE >= 2: - print("diff: %r" % diff) + print(f"diff: {diff!r}") first = self._format_output(first) second = self._format_output(second) - msg += ( - "\n---[Output:]---\n%s\n" - "---[not equal to:]---\n%s" - "\n---[diff:]---\n%s" - ) % (first, second, diff) + msg += ("\n---[Output:]---\n%s\n" "---[not equal to:]---\n%s" "\n---[diff:]---\n%s") % ( + first, + second, + diff, + ) raise self.failureException(msg) def _prepare_text(self, txt): @@ -81,7 +81,7 @@ class MarkupTest(unittest.TestCase): """ txt = txt.splitlines() assert txt[0] == "", "First assertion line must be empty! Is: %s" % repr(txt[0]) - txt = txt[1:] # Skip the first line + txt = txt[1:] # Skip the first line # get the indentation level from the first line count = False @@ -94,15 +94,17 @@ class MarkupTest(unittest.TestCase): # remove indentation from all lines txt = [i[count:].rstrip(" ") for i in txt] - #~ txt = re.sub("\n {2,}", "\n", txt) + # ~ txt = re.sub("\n {2,}", "\n", txt) txt = "\n".join(txt) # strip *one* newline at the begining... - if txt.startswith("\n"): txt = txt[1:] + if txt.startswith("\n"): + txt = txt[1:] # and strip *one* newline at the end of the text - if txt.endswith("\n"): txt = txt[:-1] - #~ print(repr(txt)) - #~ print("-"*79) + if txt.endswith("\n"): + txt = txt[:-1] + # ~ print(repr(txt)) + # ~ print("-"*79) return txt @@ -110,49 +112,57 @@ class MarkupTest(unittest.TestCase): """ Test for self._prepare_text() """ - out1 = self._prepare_text(""" + out1 = self._prepare_text( + """ one line - line two""") + line two""" + ) self.assertEqual(out1, "one line\nline two") - out2 = self._prepare_text(""" + out2 = self._prepare_text( + """ one line line two - """) + """ + ) self.assertEqual(out2, "one line\nline two") - out3 = self._prepare_text(""" + out3 = self._prepare_text( + """ one line line two - """) + """ + ) self.assertEqual(out3, "one line\n\nline two") - out4 = self._prepare_text(""" + out4 = self._prepare_text( + """ one line line two - """) + """ + ) self.assertEqual(out4, "one line\n line two\n") # removing whitespace and the end self.assertEqual(self._prepare_text("\n 111 \n 222"), "111\n222") - out5 = self._prepare_text(""" + out5 = self._prepare_text( + """ one line line two dritte Zeile - """) - self.assertEqual(out5, "one line\n line two\ndritte Zeile") - - self.assertRaises( - AssertionError, self.assertEqual, "foo", "bar" + """ ) + self.assertEqual(out5, "one line\n line two\ndritte Zeile") + self.assertRaises(AssertionError, self.assertEqual, "foo", "bar") -if __name__ == '__main__': +if __name__ == "__main__": import doctest + print("DocTest:", doctest.testmod()) unittest.main() @@ -7,7 +7,7 @@ ~~~~~~~~~~~ """ -from __future__ import division, absolute_import, print_function, unicode_literals + from creole import creole2html, html2creole, html2rest, html2textile diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..fab8cc7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,56 @@ +[tool.poetry] +name = 'python-creole' +version = '1.4.0' +description = '' +license = 'GPL-3.0-or-later' +authors = ['Jens Diemer <python-creole@jensdiemer.de>'] +homepage = 'https://github.com/jedie/python-creole/' +keywords=['creole', 'markup', 'creole2html', 'html2creole', 'rest2html', 'html2rest', 'html2textile'] +classifiers = [ + # http://pypi.python.org/pypi?%3Aaction=list_classifiers + 'Development Status :: 5 - Production/Stable', + 'Environment :: Web Environment', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GNU General Public License (GPL)', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: Implementation :: PyPy', + 'Operating System :: OS Independent', + 'Topic :: Documentation', + 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Text Processing :: Markup', + 'Topic :: Text Processing :: Markup :: HTML', + 'Topic :: Utilities', +] +packages = [ + { include = 'creole' }, +] +include = ['README.creole'] + +[tool.poetry.dependencies] +python = '^3.6' +docutils = "^0.16" + +[tool.poetry.dev-dependencies] +pytest = '^4.6' +pytest-cov = "^2.8.1" +isort = "^4.3.21" +black = "^19.10b0" +flake8 = "^3.7.9" +flynt = "^0.40.1" + +[tool.poetry.scripts] +creole2html = 'creole.cmdline:cli_creole2html' +html2creole = 'creole.cmdline:cli_html2creole' +html2rest = 'creole.cmdline:cli_html2rest' +html2textile = 'creole.cmdline:cli_html2textile' + +[build-system] +requires = ['poetry>=0.12'] +build-backend = 'poetry.masonry.api' + diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..3c40359 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,53 @@ +# +# http://doc.pytest.org/en/latest/customize.html#builtin-configuration-file-options +# https://pytest-django.readthedocs.io/en/latest/ + +[pytest] +testpaths = creole +addopts = + --verbose + + # coverage: + --cov=. + --cov-report term-missing + --no-cov-on-fail + + # Disabling warning capture + #-p no:warnings + + --showlocals + #--trace-config + --doctest-modules + + # Do not cut tracebacks (somethimes helpfull): + #--full-trace + + # exit after 5 failures: + --maxfail=5 + + # per-test capturing method: one of fd|sys|no: + #--capture=no + + # We used logging config in django, so: disable printing caught logs on failed tests. + --no-print-logs + + # run the last failures first: + --failed-first + + # re-run only failures: + #--last-failed + + # run all tests if no tests failed in the last run: + --last-failed-no-failures all + + # sort new tests first: + --new-first + +# coverage +# https://pytest-cov.readthedocs.io/en/latest/config.html +[run] +source = . +branch = True +parallel = True +omit = + */tests/*.py @@ -9,7 +9,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import os import sys |