diff options
author | Jens Diemer <github.com@jensdiemer.de> | 2020-01-19 00:17:23 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-19 00:17:23 +0100 |
commit | 5d926cdeac5f3a8a01f5c003ff0a74fa2374aa81 (patch) | |
tree | b95d2e0a3c49b415b853dd2b5e31c0387440aca1 | |
parent | c33fac617ada1a97b4f60a471f5dcf32e992fe75 (diff) | |
parent | 384a09445983c2d336cf9069663f1e6a5d150a3b (diff) | |
download | creole-5d926cdeac5f3a8a01f5c003ff0a74fa2374aa81.tar.gz |
Merge pull request #36 from jedie/poetry2
modernize project
57 files changed, 671 insertions, 751 deletions
diff --git a/.coveragerc b/.coveragerc index b7b7ca6..deb1a12 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,9 +1,11 @@ [run] branch = True source = creole +omit = + */tests/* + */site-packages/* [report] -omit = ../*migrations*,../*tests*,../*compat.* # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma 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 = E115,E124,E128,E265,E301,E309,E501 +max-line-length = 119 diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml new file mode 100644 index 0000000..a244f20 --- /dev/null +++ b/.github/workflows/pythonapp.yml @@ -0,0 +1,49 @@ +name: test + +on: [push] + +jobs: + test: + 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-poetry + source $HOME/.poetry/env + make install + + - name: List installed packages + run: | + source $HOME/.poetry/env + poetry run pip freeze + + - name: List all tox test environments + run: | + source $HOME/.poetry/env + make tox-listenvs + +# - name: Run linters +# run: | +# source $HOME/.poetry/env +# make lint + + - name: Run tests with Python v3.8 + run: | + source $HOME/.poetry/env + make tox-py38 + + - name: Run tests with Python v3.7 + run: | + source $HOME/.poetry/env + make tox-py37 + + - name: Run tests with Python v3.6 + run: | + source $HOME/.poetry/env + make tox-py36 @@ -5,4 +5,8 @@ /dist /build -.idea
\ No newline at end of file +.idea +/poetry.lock +/.coverage + +.tox 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..c2d158e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,26 +3,22 @@ language: python python: - - "2.7" - - "3.5" - - "3.6" - - "3.7" - "3.8" - - "pypy" + - "3.7" + - "3.6" - "pypy3" install: - - pip install --upgrade pip - - pip install nose textile docutils pygments coveralls - - pip install . + - make install-poetry + - source $HOME/.poetry/env + - make install + - poetry run pip freeze + - make tox-listenvs script: - - coverage run ./setup.py nosetests + - make pytest 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..669086e --- /dev/null +++ b/Makefile @@ -0,0 +1,70 @@ +SHELL := /bin/bash +MAX_LINE_LENGTH := 119 +POETRY_VERSION := $(shell poetry --version 2>/dev/null) + +help: ## List all commands + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9 -]+:.*?## / {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +check-poetry: + @if [[ "${POETRY_VERSION}" == *"Poetry"* ]] ; \ + then \ + echo "Found ${POETRY_VERSION}, ok." ; \ + else \ + echo 'Please install poetry first, with e.g.:' ; \ + echo 'make install-poetry' ; \ + exit 1 ; \ + fi + +install-poetry: ## install or update poetry + @if [[ "${POETRY_VERSION}" == *"Poetry"* ]] ; \ + then \ + echo 'Update poetry v$(POETRY_VERSION)' ; \ + poetry self update ; \ + else \ + echo 'Install poetry' ; \ + curl -sSL "https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py" | python3 ; \ + fi + +install: check-poetry ## install python-creole via 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-code-style: ## Fix code formatting +# poetry run flynt --line_length=119 creole +# poetry run isort --apply --recursive creole + poetry run autopep8 --ignore-local-config --max-line-length=${MAX_LINE_LENGTH} --aggressive --aggressive --in-place --recursive creole + +tox-listenvs: check-poetry ## List all tox test environments + poetry run tox --listenvs + +tox: check-poetry ## Run pytest via tox with all environments + poetry run tox + +tox-py36: check-poetry ## Run pytest via tox with *python v3.6* + poetry run tox -e py36 + +tox-py37: check-poetry ## Run pytest via tox with *python v3.7* + poetry run tox -e py37 + +tox-py38: check-poetry ## Run pytest via tox with *python v3.8* + poetry run tox -e py38 + +pytest: check-poetry ## Run pytest + 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 + + +.PHONY: help install lint fix test release
\ No newline at end of file diff --git a/README.creole b/README.creole index 684f1b5..ea270f3 100644 --- a/README.creole +++ b/README.creole @@ -31,6 +31,8 @@ Python packages available on: [[http://pypi.python.org/pypi/python-creole/]] ~$ pip install python-creole }}} +To setup a virtualenv via Poetry, see {{{unittests}}} section below. + == dependencies == For the most parts ({{{creole2html}}} and {{{html2creole}}}) no external libraries are needed. @@ -170,16 +172,27 @@ Creole Markup Cheat Sheet can be found here: http://www.wikicreole.org/wiki/Chea == unittests == -We use **nose** for running unittests (with DocTests). -Please install it, e.g.: {{{ -.../your/env/$ source bin/activate -.../your/env/$ pip install nose -}}} +# clone repository (or use your fork): +~$ git clone https://github.com/jedie/python-creole.git +~$ cd python-creole -To run the unittests: -{{{ -.../path/to/python-creole$ python setup.py nosetests +# install or update poetry: +~/python-crole$ make install-poetry + +# install python-creole via poetry: +~/python-crole$ make install + +# Run pytest: +~/python-crole$ make pytest + +# Run pytest via tox with all environments: +~/python-crole$ make tox + +# Run pytest via tox with one Python version: +~/python-crole$ make tox-py38 +~/python-crole$ make tox-py37 +~/python-crole$ make tox-py36 }}} @@ -193,6 +206,13 @@ Note: In this case you must install **docutils**! See above. = history = +* *dev* - [[https://github.com/jedie/python-creole/compare/v1.3.2...master|compare v1.3.2...master]] +** modernize project: +*** use poetry +*** Add a {{{Makefile}}} +*** use pytest and tox +*** remove Python v2 support +*** Test with Python v3.6, v3.7 and v3.8 * v1.3.2 - 2018-02-27 - [[https://github.com/jedie/python-creole/compare/v1.3.1...v1.3.2|compare v1.3.1...v1.3.2]] ** Adding optional img size to creole2html and html2creole contributed by [[https://github.com/JohnAD|John Dupuy]] ** run tests also with python 3.5 and 3.6 diff --git a/creole/__init__.py b/creole/__init__.py index 6594f9d..3c6a113 100644 --- a/creole/__init__.py +++ b/creole/__init__.py @@ -7,18 +7,18 @@ :homepage: http://code.google.com/p/python-creole/ - + :sourcecode: http://github.com/jedie/python-creole - + :PyPi: http://pypi.python.org/pypi/python-creole/ - :copyleft: 2008-2015 by python-creole team, see AUTHORS for more details. + :copyleft: 2008-2020 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 @@ -31,7 +31,7 @@ from creole.parser.html_parser import HtmlParser from creole.py3compat import TEXT_TYPE -__version__ = "1.3.2" +__version__ = "1.4.0" __api__ = "1.0" # Creole 1.0 spec - http://wikicreole.org/ VERSION_STRING = __version__ # remove in future @@ -49,7 +49,7 @@ def creole2html(markup_string, debug=False, >>> 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!" @@ -57,6 +57,7 @@ def creole2html(markup_string, debug=False, parser_kwargs2 = { "block_rules": block_rules, "blog_line_breaks": blog_line_breaks, + "debug": debug, } if parser_kwargs is not None: warnings.warn("parser_kwargs argument in creole2html would be removed in the future!", PendingDeprecationWarning) @@ -130,7 +131,7 @@ def html2textile(html_string, debug=False, ): """ convert html code into textile markup - + >>> html2textile('<p>This is <strong>textile <i>markup</i></strong>!</p>') 'This is *textile __markup__*!' """ @@ -157,7 +158,7 @@ def html2rest(html_string, debug=False, ): """ convert html code into ReStructuredText markup - + >>> html2rest('<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') 'This is **ReStructuredText** *markup*!' """ diff --git a/creole/cmdline.py b/creole/cmdline.py index 82a156e..78f4eb4 100644 --- a/creole/cmdline.py +++ b/creole/cmdline.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 argparse import codecs @@ -36,7 +36,7 @@ class CreoleCLI(object): default="utf-8", help="Codec for read/write file (default encoding: utf-8)" ) - + args = self.parser.parse_args() sourcefile = args.sourcefile @@ -49,7 +49,7 @@ class CreoleCLI(object): print("Convert %r to %r with %s (codec: %s)" % ( sourcefile, destination, self.convert_func.__name__, encoding )) - + with codecs.open(sourcefile, "r", encoding=encoding) as infile: with codecs.open(destination, "w", encoding=encoding) as outfile: content = infile.read() @@ -63,10 +63,10 @@ def cli_creole2html(): def cli_html2creole(): CreoleCLI(html2creole) - + def cli_html2rest(): CreoleCLI(html2rest) - + def cli_html2textile(): CreoleCLI(html2textile) diff --git a/creole/emitter/creol2html_emitter.py b/creole/emitter/creol2html_emitter.py index 2879f4e..0fa0def 100644 --- a/creole/emitter/creol2html_emitter.py +++ b/creole/emitter/creol2html_emitter.py @@ -9,7 +9,7 @@ """ -from __future__ import division, absolute_import, print_function, unicode_literals + import json from xml.sax.saxutils import escape @@ -167,7 +167,7 @@ class HtmlEmitter(object): return self.html_escape(node.content) def separator_emit(self, node): - return '<hr />\n\n' + return '<hr />\n' def paragraph_emit(self, node): return '<p>%s</p>\n' % self.emit_children(node) diff --git a/creole/emitter/html2creole_emitter.py b/creole/emitter/html2creole_emitter.py index 2e9c31c..00fd142 100644 --- a/creole/emitter/html2creole_emitter.py +++ b/creole/emitter/html2creole_emitter.py @@ -10,7 +10,7 @@ :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 diff --git a/creole/emitter/html2rest_emitter.py b/creole/emitter/html2rest_emitter.py index 7a32872..41891fe 100644 --- a/creole/emitter/html2rest_emitter.py +++ b/creole/emitter/html2rest_emitter.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 posixpath from creole.shared.base_emitter import BaseEmitter diff --git a/creole/emitter/html2textile_emitter.py b/creole/emitter/html2textile_emitter.py index 2263c12..e43b0df 100644 --- a/creole/emitter/html2textile_emitter.py +++ b/creole/emitter/html2textile_emitter.py @@ -10,7 +10,7 @@ :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 diff --git a/creole/exceptions.py b/creole/exceptions.py index 44cddff..91f9042 100644 --- a/creole/exceptions.py +++ b/creole/exceptions.py @@ -4,12 +4,12 @@ """ 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..2f6104a 100644 --- a/creole/html_tools/deentity.py +++ b/creole/html_tools/deentity.py @@ -3,14 +3,14 @@ """ 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: @@ -39,7 +39,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]=-' diff --git a/creole/html_tools/strip_html.py b/creole/html_tools/strip_html.py index 20b6788..10534ad 100644 --- a/creole/html_tools/strip_html.py +++ b/creole/html_tools/strip_html.py @@ -4,14 +4,14 @@ """ 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 diff --git a/creole/html_tools/text_tools.py b/creole/html_tools/text_tools.py index 28be3c9..5843cf6 100644 --- a/creole/html_tools/text_tools.py +++ b/creole/html_tools/text_tools.py @@ -4,14 +4,14 @@ """ 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 diff --git a/creole/parser/creol2html_parser.py b/creole/parser/creol2html_parser.py index ab09a35..63f3b14 100644 --- a/creole/parser/creol2html_parser.py +++ b/creole/parser/creol2html_parser.py @@ -22,9 +22,10 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import re +from pprint import pformat from creole.parser.creol2html_rules import BlockRules, INLINE_FLAGS, INLINE_RULES, \ SpecialRules, InlineRules @@ -59,18 +60,19 @@ class CreoleParser(object): inline_re = re.compile('|'.join(INLINE_RULES), INLINE_FLAGS) - def __init__(self, raw, block_rules=None, blog_line_breaks=True): + def __init__(self, raw, block_rules=None, blog_line_breaks=True, debug=False): assert isinstance(raw, TEXT_TYPE) self.raw = raw if block_rules is None: block_rules = BlockRules(blog_line_breaks=blog_line_breaks) + self.blog_line_breaks = blog_line_breaks + self.debug = debug # TODO: use logging + # setup block element rules: 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 @@ -126,7 +128,7 @@ class CreoleParser(object): text = groups.get('text', "") - if groups.get('space'): + if groups.get('space') and self.cur.children: # use wikipedia style line breaks and seperate a new line with one space text = " " + text @@ -423,17 +425,18 @@ class CreoleParser(object): 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): + data = dict([ + group for group in groups.items() if group[1] is not None + ]) + print(pformat(data)) groups = match.groupdict() for name, text in groups.items(): if text is not None: - #if name != "char": debug(groups) + if self.debug and name != "char": + # TODO: use logging + debug(groups) replace_method = getattr(self, '_%s_repl' % name) replace_method(groups) return @@ -450,12 +453,15 @@ class CreoleParser(object): """Parse the text given as self.raw and return DOM tree.""" # convert all lineendings to \n text = self.raw.replace("\r\n", "\n").replace("\r", "\n") + if self.debug: + # TODO: use logging + print(repr(text)) self.parse_block(text) return self.root #-------------------------------------------------------------------------- - def debug(self, start_node=None): + def debug_tree(self, start_node=None): """ Display the current document tree """ diff --git a/creole/parser/creol2html_rules.py b/creole/parser/creol2html_rules.py index 01bb08e..0a9f059 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 @@ -52,12 +52,12 @@ class InlineRules(object): # ''' % proto # image tag - image = r'''(?P<image> + image = r'''(?i)(?P<image> {{ (?P<image_target>.+?) \s* (\| \s* (?P<image_text>.+?) \s*)? }} - )(?i)''' + )''' #-------------------------------------------------------------------------- # a macro like: <<macro>>text<</macro>> @@ -133,7 +133,7 @@ class BlockRules(object): (?P<head_text> .*? ) (=|\s)*?$ )''' - separator = r'(?P<separator> ^ \s* ---- \s* $ )' # horizontal line + separator = r'(?P<separator> ^ \s* ----) [ \t]* $' # horizontal line pre_block = r'''(?P<pre_block> ^{{{ \s* $ @@ -144,10 +144,10 @@ class BlockRules(object): ^}}}) ''' - # Matches the whole list, separate items are parsed later. The - # list *must* start with a single bullet. + # Matches the whole list, separate items are parsed later. + # The list *must* start with a single bullet. list = r'''(?P<list> - ^ [ \t]* ([*][^*\#]|[\#][^\#*]).* $ + ^ \s* ([*][^*\#]|[\#][^\#*]).* $ ( \n[ \t]* [*\#]+.* $ )* )''' @@ -160,7 +160,7 @@ class BlockRules(object): def __init__(self, blog_line_breaks=True): if blog_line_breaks: - # use blog style line breaks (every line break would be converted into <br />) + # 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 @@ -224,11 +224,11 @@ INLINE_RULES = ( 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. """ diff --git a/creole/parser/html_parser.py b/creole/parser/html_parser.py index fa60091..4380431 100644 --- a/creole/parser/html_parser.py +++ b/creole/parser/html_parser.py @@ -10,7 +10,7 @@ :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 @@ -50,7 +50,7 @@ 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 +63,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> diff --git a/creole/parser/html_parser_config.py b/creole/parser/html_parser_config.py index 9790833..ddbda8f 100644 --- a/creole/parser/html_parser_config.py +++ b/creole/parser/html_parser_config.py @@ -4,14 +4,14 @@ """ 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", diff --git a/creole/py3compat.py b/creole/py3compat.py index f48da75..76c55b4 100644 --- a/creole/py3compat.py +++ b/creole/py3compat.py @@ -3,16 +3,16 @@ """ 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 diff --git a/creole/rest_tools/clean_writer.py b/creole/rest_tools/clean_writer.py index 5378bd7..2b6ae66 100644 --- a/creole/rest_tools/clean_writer.py +++ b/creole/rest_tools/clean_writer.py @@ -4,19 +4,19 @@ """ 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 sys @@ -193,13 +193,13 @@ class CleanHTMLTranslator(html4css1.HTMLTranslator, object): 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): ... diff --git a/creole/rest_tools/pypi_rest2html.py b/creole/rest_tools/pypi_rest2html.py index fd7d16d..c60ae0c 100644 --- a/creole/rest_tools/pypi_rest2html.py +++ b/creole/rest_tools/pypi_rest2html.py @@ -11,7 +11,7 @@ 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 diff --git a/creole/setup_utils.py b/creole/setup_utils.py index 977cb73..6f6b651 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 diff --git a/creole/shared/HTMLParsercompat.py b/creole/shared/HTMLParsercompat.py index 67529d8..6f61cc5 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,12 +13,12 @@ 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 # --------------------------------------------------------------------- add end @@ -556,7 +556,7 @@ class HTMLParser(_markupbase.ParserBase): 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: @@ -584,6 +584,6 @@ class HTMLParser(_markupbase.ParserBase): 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 + # -------------------------------------------------------- change end diff --git a/creole/shared/base_emitter.py b/creole/shared/base_emitter.py index 1561083..de6fd2f 100644 --- a/creole/shared/base_emitter.py +++ b/creole/shared/base_emitter.py @@ -10,7 +10,7 @@ :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 diff --git a/creole/shared/document_tree.py b/creole/shared/document_tree.py index 527e4f9..4971953 100644 --- a/creole/shared/document_tree.py +++ b/creole/shared/document_tree.py @@ -10,7 +10,7 @@ :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 @@ -22,7 +22,7 @@ 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): diff --git a/creole/shared/example_macros.py b/creole/shared/example_macros.py index 2eb85d8..428d5d2 100644 --- a/creole/shared/example_macros.py +++ b/creole/shared/example_macros.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 diff --git a/creole/shared/unknown_tags.py b/creole/shared/unknown_tags.py index 4e3e079..fe231f0 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 @@ -42,7 +42,7 @@ def _mask_content(emitter, node, mask_tag): def raise_unknown_node(emitter, node): """ unknown_emit callable for Html2CreoleEmitter - + Raise NotImplementedError on unknown tags. """ content = emitter.emit_children(node) @@ -56,7 +56,7 @@ def raise_unknown_node(emitter, node): 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 +65,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 +74,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() @@ -99,8 +99,8 @@ def escape_unknown_nodes(emitter, node): 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..f1b981d 100644 --- a/creole/shared/utils.py +++ b/creole/shared/utils.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 shlex import json diff --git a/creole/tests/test_Makefile.py b/creole/tests/test_Makefile.py new file mode 100644 index 0000000..dbf129c --- /dev/null +++ b/creole/tests/test_Makefile.py @@ -0,0 +1,29 @@ + +""" + :copyleft: 2020 by python-creole team, see AUTHORS for more details. + :license: GNU GPL v3 or above, see LICENSE for more details. +""" + +import unittest + +from creole.tests.utils.unittest_subprocess import SubprocessMixin + + +class MakefileTestCase(unittest.TestCase, SubprocessMixin): + + def test_help(self): + popen_args, retcode, stdout = self.subprocess( + popen_args=["make"], + ) + assert "List all commands" in stdout + assert "tox" in stdout + assert "pytest" in stdout + assert retcode == 0 + + def test_check_poetry(self): + popen_args, retcode, stdout = self.subprocess( + popen_args=["make", "check-poetry"], + ) + assert "Found Poetry version 1." in stdout + assert "ok" in stdout + assert retcode == 0 diff --git a/creole/tests/test_cli.py b/creole/tests/test_cli.py index 5be41d5..74fc7d7 100644 --- a/creole/tests/test_cli.py +++ b/creole/tests/test_cli.py @@ -5,11 +5,11 @@ unittest for CLI ~~~~~~~~~~~~~~~~ - :copyleft: 2013-2015 by python-creole team, see AUTHORS for more details. + :copyleft: 2013-2020 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 subprocess import unittest @@ -83,7 +83,6 @@ class CreoleCLITests(BaseCreoleTest, SubprocessMixin, CliTestMixins): self.assertSubprocess( popen_args=[cli_str, sourcefilepath, destfilepath], retcode=0, stdout=stdout, - verbose=False, ) dest_file.seek(0) @@ -101,7 +100,6 @@ class CreoleCLITests(BaseCreoleTest, SubprocessMixin, CliTestMixins): popen_args=[cmd, "--version"], retcode=0, stdout=version_info, - verbose=False, ) diff --git a/creole/tests/test_creole2html.py b/creole/tests/test_creole2html.py index 4e21e13..b75435d 100644 --- a/creole/tests/test_creole2html.py +++ b/creole/tests/test_creole2html.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 sys import unittest @@ -204,12 +204,8 @@ class TestCreole2html(BaseCreoleTest): error_msg = my_stderr.getvalue() self.assertEqual(error_msg, "") + @unittest.skipIf(not PYGMENTS, "Pygments not installed") def test_code_macro(self): - if not PYGMENTS: - # TODO: Use @unittest.skipIf if python 2.6 will be not support anymore - warnings.warn("Skip test, because 'pygments' is not installed.") - return - # 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""" @@ -220,8 +216,8 @@ class TestCreole2html(BaseCreoleTest): <</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 /> + <div class="pygments"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">xrange</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span><br /> + <span class="nb">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} @@ -813,7 +809,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): ...and not blog styled. """), - parser_kwargs={"blog_line_breaks":False}, + blog_line_breaks=False, + debug=True, verbose=True ) self.assertEqual(html, self._prepare_text(""" <p>wiki style linebreaks</p> @@ -830,7 +827,8 @@ class TestCreole2htmlMarkup(BaseCreoleTest): * one * two """), - parser_kwargs={"blog_line_breaks":False}, + blog_line_breaks=False, + debug=True, verbose=True ) self.assertEqual(html, self._prepare_text(""" <p><strong>one</strong> <i>two</i></p> @@ -857,7 +855,7 @@ class TestCreole2htmlMarkup(BaseCreoleTest): end """), - parser_kwargs={"blog_line_breaks":False}, + blog_line_breaks=False, ) self.assertEqual(html, self._prepare_text(""" <p>with blog line breaks, every line break would be convertet into<br /> with wiki style not.</p> diff --git a/creole/tests/test_cross_compare_all.py b/creole/tests/test_cross_compare_all.py index 58259d1..b10f59a 100644 --- a/creole/tests/test_cross_compare_all.py +++ b/creole/tests/test_cross_compare_all.py @@ -18,7 +18,7 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import division, absolute_import, print_function, unicode_literals + import unittest diff --git a/creole/tests/test_cross_compare_creole.py b/creole/tests/test_cross_compare_creole.py index 6431fc0..ea48603 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,13 +48,13 @@ 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> """ @@ -132,7 +132,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 +143,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): """, html_string=""" <h3>Closing braces in nowiki:</h3> - + <pre> if (x != NULL) { for (i = 0; i < size; i++) { @@ -156,14 +156,14 @@ class CrossCompareCreoleTests(BaseCreoleTest): def test_pre2(self): self.cross_compare_creole(r""" 111 - + {{{ //This// does **not** get [[formatted]] }}} 222 one - + {{{ foo @@ -172,14 +172,14 @@ class CrossCompareCreoleTests(BaseCreoleTest): two """, """ <p>111</p> - + <pre> //This// does **not** get [[formatted]] </pre> <p>222</p> - + <p>one</p> - + <pre> foo @@ -191,7 +191,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): def test_pre(self): self.cross_compare_creole(r""" start - + {{{ * no list <html escaped> @@ -199,7 +199,7 @@ class CrossCompareCreoleTests(BaseCreoleTest): end """, """ <p>start</p> - + <pre> * no list <html escaped> @@ -219,16 +219,16 @@ class CrossCompareCreoleTests(BaseCreoleTest): 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> """ ) diff --git a/creole/tests/test_cross_compare_rest.py b/creole/tests/test_cross_compare_rest.py index c40e924..454d6e5 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 diff --git a/creole/tests/test_cross_compare_textile.py b/creole/tests/test_cross_compare_textile.py index 2a0681a..fbbd871 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 diff --git a/creole/tests/test_html2creole.py b/creole/tests/test_html2creole.py index 58a20ef..df7c951 100644 --- a/creole/tests/test_html2creole.py +++ b/creole/tests/test_html2creole.py @@ -5,15 +5,15 @@ """ 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 @@ -136,7 +136,7 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): ) def test_transparent_unknown_nodes2(self): - """ + """ HTMLParser has problems with <script> tags. See: http://bugs.python.org/issue670664 """ @@ -163,7 +163,7 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): """, unknown_emit=transparent_unknown_nodes ) - #-------------------------------------------------------------------------- + #-------------------------------------------------------------------------- def test_entities(self): """ @@ -224,7 +224,7 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): def test_tbody_table(self): self.assert_html2creole(r""" Ignore 'tbody' tag in tables: - + |= Headline 1 |= Headline 2 | | cell one | cell two | end @@ -327,7 +327,7 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): """ self.assert_html2creole(r""" **foo** - + * one """, """ <b>foo</b><ul><li>one</li></ul> @@ -409,9 +409,9 @@ class TestHtml2CreoleMarkup(BaseCreoleTest): def test_horizontal_rule(self): self.assert_html2creole(r""" one - + ---- - + two """, """ <p>one</p> diff --git a/creole/tests/test_html2rest.py b/creole/tests/test_html2rest.py index 9056d54..eb7de66 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=""" @@ -74,17 +74,20 @@ class ReStTests(BaseCreoleTest): def test_pre_code1(self): self.assert_html2rest( rest_string=""" + Text line + :: - + >>> from creole import creole2html >>> creole2html("This is **creole //markup//**") - '<p>This is <strong>creole <i>markup</i></strong></p> + '<p>This is <strong>creole <i>markup</i></strong></p>' """, html_string=""" + <p>Text line</p> <pre> >>> from creole import creole2html >>> creole2html("This is **creole //markup//**") - '<p>This is <strong>creole <i>markup</i></strong></p>\n' + '<p>This is <strong>creole <i>markup</i></strong></p>' </pre> """ ) @@ -117,21 +120,21 @@ class ReStTests(BaseCreoleTest): 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=""" @@ -195,16 +198,16 @@ class ReStTests(BaseCreoleTest): </table> """ ) - + def test_duplicate_substitution1(self): self.assertRaises(Html2restException, self.assert_html2rest, rest_string=""" +-----------------------------+ | this is `same`_ first time. | +-----------------------------+ - + .. _same: /first/ - + the `same </other/>`_ link? """, html_string=""" @@ -216,7 +219,7 @@ class ReStTests(BaseCreoleTest): """, # debug=True ) - + def test_duplicate_link_substitution(self): self.assertRaises(Html2restException, self.assert_html2rest, # self.cross_compare( @@ -224,9 +227,9 @@ class ReStTests(BaseCreoleTest): +-----------------------------+ | this is `same`_ first time. | +-----------------------------+ - + .. _same: /first/ - + the `same </other/>`_ link? """, html_string=""" @@ -245,7 +248,7 @@ class ReStTests(BaseCreoleTest): rest_string=""" a |image|... and a other |image|! - + .. |image| image:: /image.png .. |image| image:: /other.png """, @@ -266,13 +269,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 +284,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,13 +292,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> # """, # ) diff --git a/creole/tests/test_html2textile.py b/creole/tests/test_html2textile.py index f02fced..b26b3e9 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 @@ -46,13 +46,13 @@ 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} @@ -61,7 +61,7 @@ class TextileTests(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. """ @@ -75,7 +75,7 @@ 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> """, ) diff --git a/creole/tests/test_macros.py b/creole/tests/test_macros.py index a5194f9..2a036be 100644 --- a/creole/tests/test_macros.py +++ b/creole/tests/test_macros.py @@ -4,15 +4,15 @@ """ 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 @@ -20,10 +20,10 @@ 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]' """ @@ -40,4 +40,4 @@ def unittest_macro2(char, text): 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..23261d9 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 @@ -24,7 +24,7 @@ class ReSt2HtmlTests(BaseCreoleTest): self.assert_rest2html(""" :homepage: http://code.google.com/p/python-creole/ - + :sourcecode: http://github.com/jedie/python-creole """, """ @@ -61,17 +61,17 @@ class ReSt2HtmlTests(BaseCreoleTest): def test_clean_list(self): self.assert_rest2html(""" * item 1 - + * item 1.1 - + * item 1.2 - + * item 2 - + numbered list: - + #. item A - + #. item B """, """ <ul> @@ -96,7 +96,7 @@ class ReSt2HtmlTests(BaseCreoleTest): ====== head 1 ====== - + ------ head 2 ------ @@ -108,7 +108,7 @@ class ReSt2HtmlTests(BaseCreoleTest): def test_include_disabled_by_default(self): self.assert_rest2html(""" Include should be disabled by default. - + .. include:: doesntexist.txt """, """ <p>Include should be disabled by default.</p> @@ -122,7 +122,7 @@ class ReSt2HtmlTests(BaseCreoleTest): temp.flush() self.assert_rest2html(""" Enable include and test it. - + .. include:: %s """ % temp.name, """ <p>Enable include and test it.</p> @@ -132,7 +132,7 @@ class ReSt2HtmlTests(BaseCreoleTest): def test_raw_disabled_by_default(self): self.assert_rest2html(""" Raw directive should be disabled by default. - + .. raw:: html <hr width=50 size=10> @@ -143,7 +143,7 @@ class ReSt2HtmlTests(BaseCreoleTest): def test_raw_enabled(self): self.assert_rest2html(""" Now RAW is enabled. - + .. raw:: html <hr width=50 size=10> diff --git a/creole/tests/test_setup.py b/creole/tests/test_setup.py deleted file mode 100644 index 52524dc..0000000 --- a/creole/tests/test_setup.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -""" - unittest for CLI - ~~~~~~~~~~~~~~~~ - - :copyleft: 2013-2015 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 -import sys -import os - -import creole -from creole.tests.utils.unittest_subprocess import SubprocessMixin - - -class TestSetup(unittest.TestCase, SubprocessMixin): - @classmethod - def setUpClass(cls): - cls.setup_path = os.path.join(os.path.dirname(creole.__file__), "..", "setup.py") - - 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) - - def test_version(self): - self.assertSubprocess( - popen_args=(sys.executable, self.setup_path, "--version"), - retcode=0, - stdout=creole.VERSION_STRING, - 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..3025543 100644 --- a/creole/tests/test_setup_utils.py +++ b/creole/tests/test_setup_utils.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 + import unittest import os diff --git a/creole/tests/test_subprocess.py b/creole/tests/test_subprocess.py index 6babded..fcce3bc 100644 --- a/creole/tests/test_subprocess.py +++ b/creole/tests/test_subprocess.py @@ -4,41 +4,23 @@ unittest ~~~~~~~~ - :copyleft: 2015 by python-creole team, see AUTHORS for more details. + :copyleft: 2015-2020 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 -import sys import os +import sys +import unittest 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 - self.assertRegex = self.assertRegexpMatches - self.assertRegex(filepath, ".*?python.*?") - - def test_executable_not_exists(self): - with self.assertRaisesRegexp(AssertionError, """Program "doesn't exists!" not found in:.*"""): - self.find_executable("doesn't exists!") - - def test_executable_with_path(self): - msg = "'%s' unexpectedly found in '%s'" % ( - os.sep, 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 ) self.assertEqual(stdout, "to stdout") self.assertEqual(retcode, 0) @@ -64,6 +46,4 @@ class TestSubprocessMixin(unittest.TestCase, SubprocessMixin): "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..5131a16 100644 --- a/creole/tests/test_utils.py +++ b/creole/tests/test_utils.py @@ -9,15 +9,73 @@ :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 test_assertEqual(self): + self.assertRaises( + AssertionError, self.assertEqual, "foo", "bar" + ) + + def test_prepare_text_base(self): + out1 = self._prepare_text(""" + one line + line two""") + self.assertEqual(out1, "one line\nline two") + + out2 = self._prepare_text(""" + one line + line two + """) + self.assertEqual(out2, "one line\nline two") + + def test_prepare_text_last_line_empty(self): + + out3 = self._prepare_text(""" + one line + line two + + """) + self.assertEqual(out3, "one line\nline two\n") + + def test_prepare_text_empty_line(self): + self.assertEqual(self._prepare_text(""" + line one + + line two + """), "line one\n\nline two") + + def test_prepare_text_first_line_empty(self): + self.assertEqual(self._prepare_text(""" + + line one + line two + """), "\nline one\nline two") + + def test_prepare_space_and_line_end(self): + self.assertEqual(self._prepare_text("\n 111 \n 222"), "111\n222") + + def test_prepare_text_indent_line(self): + self.assertEqual("line one\n indent line\nline two", self._prepare_text(""" + line one + indent line + line two + """)) + + def test_prepare_text_indent_with_empty_end(self): + out4 = self._prepare_text(""" + one line + line two + + """) + self.assertEqual(out4, "one line\n line two\n") + def assertEqual2(self, first, second, msg=""): self.assertNotEqual(first, second, msg) diff --git a/creole/tests/utils/base_unittest.py b/creole/tests/utils/base_unittest.py index f9002fa..fb21245 100644 --- a/creole/tests/utils/base_unittest.py +++ b/creole/tests/utils/base_unittest.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 + import re import warnings @@ -86,29 +86,17 @@ class BaseCreoleTest(MarkupTest): text = text.replace("\n", "\\n\n") text = text.replace("\t", "\\t") - print + print() print("_" * 79) - print(" Debug Text: %s" % msg) + print(" Debug Text: %s:" % msg) print(text) print("-" * 79) - def assertIn(self, member, container, *args, **kwargs): - """ - Assert member in container. - assertIn is new in Python 2.7 - """ - try: - f = super(BaseCreoleTest, self).assertIn - except AttributeError: - self.assertTrue(member in container, *args, **kwargs) - else: - f(member, container, *args, **kwargs) - def assert_creole2html( self, raw_creole, raw_html, - strip_lines=False, debug=False, + strip_lines=False, debug=True, parser_kwargs={}, emitter_kwargs={}, - block_rules=None, blog_line_breaks=True, macros=None, verbose=None, stderr=None, + block_rules=None, blog_line_breaks=True, macros=None, verbose=True, stderr=None, strict=False, ): """ @@ -127,18 +115,16 @@ class BaseCreoleTest(MarkupTest): assert isinstance(html_string, TEXT_TYPE) if strip_lines: html_string = strip_html_lines(html_string, strip_lines) - if debug: - self._debug_text("assert_creole2html() html_string", html_string) + self._debug_text("assert_creole2html() html_string reference", html_string) # convert creole markup into html code out_string = creole2html( - markup_string, debug, + markup_string, debug=debug, block_rules=block_rules, blog_line_breaks=blog_line_breaks, macros=macros, verbose=verbose, stderr=stderr, strict=strict, ) - if debug: - self._debug_text("assert_creole2html() creole2html", out_string) + self._debug_text("assert_creole2html() creole2html output", out_string) if strip_lines: out_string = strip_html_lines(out_string, strip_lines) @@ -149,7 +135,7 @@ class BaseCreoleTest(MarkupTest): self.assertEqual(out_string, html_string, msg="creole2html") def assert_html2creole2(self, creole, html, - debug=False, + debug=True, unknown_emit=None, strict=False, ): @@ -157,8 +143,7 @@ class BaseCreoleTest(MarkupTest): out_string = html2creole( html, debug, unknown_emit=unknown_emit, strict=strict ) - if debug: - self._debug_text("assert_html2creole() html2creole", out_string) + self._debug_text("assert_html2creole() html2creole", out_string) # compare self.assertEqual(out_string, creole, msg="html2creole") @@ -195,7 +180,7 @@ class BaseCreoleTest(MarkupTest): self.assert_html2creole2(creole, html, debug, unknown_emit, strict) def cross_compare_creole(self, creole_string, html_string, - strip_lines=False, debug=False, + strip_lines=False, debug=True, # creole2html old API: creole_parser_kwargs={}, html_emitter_kwargs={}, # html2creole old API: @@ -221,13 +206,14 @@ class BaseCreoleTest(MarkupTest): self.assertNotEqual(creole_string, html_string) self.assert_creole2html( - creole_string, html_string, strip_lines, debug, + raw_creole=creole_string, raw_html=html_string, + strip_lines=strip_lines, block_rules=block_rules, blog_line_breaks=blog_line_breaks, macros=macros, stderr=stderr, ) self.assert_html2creole( - creole_string, html_string, strip_lines, debug, + raw_creole=creole_string, raw_html=html_string, strip_lines=strip_lines, unknown_emit=unknown_emit, ) @@ -294,17 +280,19 @@ class BaseCreoleTest(MarkupTest): self.assertNotEqual(rest_string, html_string) rest_string = self._prepare_text(rest_string) + print("-" * 100) + print(rest_string) html_string = self._prepare_text(html_string) - if strip_lines: html_string = strip_html_lines(html_string, strip_lines) + print("-" * 100) + print(html_string) # compare html -> reStructuredText rest_string2 = html2rest(html_string, debug, parser_kwargs, emitter_kwargs) - if debug: - print("-" * 79) - print(rest_string2) - print("-" * 79) + print("-" * 100) + print(rest_string2) + print("-" * 100) self.assertEqual(rest_string2, rest_string, msg="html2rest") diff --git a/creole/tests/utils/unittest_subprocess.py b/creole/tests/utils/unittest_subprocess.py index bca3779..16ef649 100644 --- a/creole/tests/utils/unittest_subprocess.py +++ b/creole/tests/utils/unittest_subprocess.py @@ -1,65 +1,65 @@ -# coding: utf-8 - """ unittest subprocess helper ~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyleft: 2015 by python-creole team, see AUTHORS for more details. + :copyleft: 2015-2020 by python-creole team, see AUTHORS for more details. :license: GNU GPL v3 or above, see LICENSE for more details. """ -from __future__ import print_function, unicode_literals -import json import os +import shutil import subprocess import sys +from pathlib import Path -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) +class SubprocessMixin: - def find_executable(self, program): - self.assertNotIn(os.sep, program) - for path in self.SEARCH_PATH: - 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) - else: - return filepath + def subprocess(self, popen_args): + assert isinstance(popen_args, (tuple, list)) - self.fail("Program %s not found in:\n\t* %s" % (json.dumps(program), "\n\t* ".join(self.SEARCH_PATH))) + print("Call:", popen_args) - def subprocess(self, popen_args, verbose=True): - assert isinstance(popen_args, (tuple, list)) + # Expand PATH + bin_path = str(Path(sys.executable).parent) + if bin_path not in os.environ["PATH"]: + # .../venv/bin will be not in PATH in tests, just add it + # so that installed [tool.poetry.scripts] will be found + os.environ["PATH"] += os.pathsep + bin_path - if verbose: - print("Call:", popen_args) + # Check if executeable will be found + prog = popen_args[0] + cmd = shutil.which(prog) + assert cmd is not None, f'{prog!r} not found in PATH: {os.environ.get("PATH")!r}!' try: - process = subprocess.Popen(popen_args, + 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() + print("="*100) + print("stdout:") + print("-"*100) + print(stdout) + print("-"*100) return popen_args, retcode, stdout - def assertSubprocess(self, popen_args, retcode, stdout, verbose=True): - popen_args2, retcode2, stdout2 = self.subprocess(popen_args, verbose) + def assertSubprocess(self, popen_args, retcode, stdout): + popen_args2, retcode2, stdout2 = self.subprocess(popen_args) stdout = stdout.strip() try: self.assertEqual(stdout, stdout2, "stdout wrong:") @@ -78,5 +78,3 @@ class SubprocessMixin(object): stdout2, ) self.fail(msg) - - diff --git a/creole/tests/utils/utils.py b/creole/tests/utils/utils.py index 5e2b24a..005f6c4 100644 --- a/creole/tests/utils/utils.py +++ b/creole/tests/utils/utils.py @@ -11,14 +11,12 @@ :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: +# error output format: # =1 -> via repr() # =2 -> raw VERBOSE = 1 @@ -41,6 +39,7 @@ 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: @@ -50,109 +49,37 @@ class MarkupTest(unittest.TestCase): return txt def assertEqual(self, first, second, msg=""): - if not first == second: - if VERBOSE >= 2: - print("first: %r" % first) - print("second: %r" % second) - - #~ 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))) - - if VERBOSE >= 2: - print("diff: %r" % diff) - - 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) - raise self.failureException(msg) - - def _prepare_text(self, txt): - """ - prepare the multiline, indentation text. - """ - txt = txt.splitlines() - assert txt[0] == "", "First assertion line must be empty! Is: %s" % repr(txt[0]) - txt = txt[1:] # Skip the first line - - # get the indentation level from the first line - count = False - for count, char in enumerate(txt[0]): - if char != " ": - break - - assert count != False, "second line is empty!" + if first == second: + return - # remove indentation from all lines - txt = [i[count:].rstrip(" ") for i in txt] + try: + diff = make_diff(first, second) + except AttributeError: + raise self.failureException(f"{first!r} is not {second!r}") - #~ txt = re.sub("\n {2,}", "\n", txt) - txt = "\n".join(txt) + print("*" * 100) + print("---[Output:]-----------------------------------------------------------------------------------------") + print(first) + print("---[not equal to:]-----------------------------------------------------------------------------------") + print(second) + print("---[diff:]-------------------------------------------------------------------------------------------") + print(diff) + print("*" * 100) - # strip *one* newline at the begining... - 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) + assert first == second, f"{first!r} is not {second!r}" - return txt - - def testSelf(self): + def _prepare_text(self, txt): """ - Test for self._prepare_text() + prepare the multiline, indentation text. """ - out1 = self._prepare_text(""" - one line - line two""") - self.assertEqual(out1, "one line\nline two") - - out2 = self._prepare_text(""" - one line - line two - """) - self.assertEqual(out2, "one line\nline two") - - out3 = self._prepare_text(""" - one line - - line two - """) - self.assertEqual(out3, "one line\n\nline two") - - out4 = self._prepare_text(""" - one line - line two - - """) - self.assertEqual(out4, "one line\n line two\n") + # Remove any common leading whitespace from every line + txt = textwrap.dedent(txt) - # removing whitespace and the end - self.assertEqual(self._prepare_text("\n 111 \n 222"), "111\n222") + # Strip spaces and every line end and remove the last line ending: + txt = "\n".join(line.rstrip(" ") for line in txt.splitlines()) - out5 = self._prepare_text(""" - one line - line two - dritte Zeile - """) - self.assertEqual(out5, "one line\n line two\ndritte Zeile") + # strip *one* newline at the beginning... + if txt.startswith("\n"): + txt = txt[1:] - self.assertRaises( - AssertionError, self.assertEqual, "foo", "bar" - ) - - - -if __name__ == '__main__': - import doctest - print("DocTest:", doctest.testmod()) - - unittest.main() + return txt diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ac0bba0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,57 @@ +[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 :: 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] +tox = "^3.14.3" +pygments = "^2.5.2" +textile = "^4.0.0" +pytest = '^4.6' +pytest-cov = "^2.8.1" +isort = "^4.3.21" +flake8 = "^3.7.9" +flynt = "^0.40.1" +autopep8 = "^1.4.4" + +[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..8f0c9ee --- /dev/null +++ b/pytest.ini @@ -0,0 +1,50 @@ +# +# 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 + + # 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 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b0a6182..0000000 --- a/setup.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[flake8] -ignore=E115,E124,E128,E265,E301,E309,E501 -max-line-length = 119 - -[metadata] -license-file = LICENSE - -[bdist_wheel] -universal = 1 - -[nosetests] -verbose=True -verbosity=2 -detailed-errors=1 -with-doctest=1
\ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100755 index 9aaf85e..0000000 --- a/setup.py +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -""" - distutils setup - ~~~~~~~~~~~~~~~ - - :copyleft: 2009-2018 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 - -import os -import sys -import subprocess -import shutil - -from setuptools import setup, find_packages, Command - -try: - from creole import __version__ -except ImportError: - __version__ = "<unknown>" - -PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__)) - -#_____________________________________________________________________________ -# convert creole to ReSt on-the-fly, see also: -# https://github.com/jedie/python-creole/wiki/Use-In-Setup -long_description = None -for arg in ("test", "check", "register", "sdist", "--long-description"): - if arg in sys.argv: - try: - from creole.setup_utils import get_long_description - except ImportError as err: - raise ImportError("%s - Please install python-creole - e.g.: pip install python-creole" % err) - else: - long_description = get_long_description(PACKAGE_ROOT) - break -#---------------------------------------------------------------------------- - - -if "test" in sys.argv or "nosetests" in sys.argv: - """ - nose is a optional dependency, so test import. - Otherwise the user get only the error: - error: invalid command 'nosetests' - """ - try: - import nose - except ImportError as err: - print("\nError: Can't import 'nose': %s" % err) - print("\nMaybe 'nose' is not installed or virtualenv not activated?!?") - print("e.g.:") - print(" ~/your/env/$ source bin/activate") - print(" ~/your/env/$ pip install nose") - print(" ~/your/env/$ ./setup.py nosetests\n") - sys.exit(-1) - else: - if "test" in sys.argv: - print("\nPlease use 'nosetests' instead of 'test' to cover all tests!\n") - print("e.g.:") - print(" $ ./setup.py nosetests\n") - sys.exit(-1) - - -def get_authors(): - try: - with open(os.path.join(PACKAGE_ROOT, "AUTHORS"), "r") as f: - authors = [l.strip(" *\r\n") for l in f if l.strip().startswith("*")] - except Exception: - evalue = sys.exc_info()[1] - authors = "[Error: %s]" % evalue - return authors - - -if "publish" in sys.argv: - """ - 'publish' helper for setup.py - - Build and upload to PyPi, if... - ... __version__ doesn't contains "dev" - ... we are on git 'master' branch - ... git repository is 'clean' (no changed files) - - Upload with "twine", git tag the current version and git push --tag - - The cli arguments will be pass to 'twine'. So this is possible: - * Display 'twine' help page...: ./setup.py publish --help - * use testpypi................: ./setup.py publish --repository=test - - TODO: Look at: https://github.com/zestsoftware/zest.releaser - - Source: https://github.com/jedie/python-code-snippets/blob/master/CodeSnippets/setup_publish.py - copyleft 2015-2017 Jens Diemer - GNU GPL v2+ - """ - if sys.version_info[0] == 2: - input = raw_input - - import_error = False - try: - # Test if wheel is installed, otherwise the user will only see: - # error: invalid command 'bdist_wheel' - import wheel - except ImportError as err: - print("\nError: %s" % err) - print("\nMaybe https://pypi.org/project/wheel is not installed or virtualenv not activated?!?") - print("e.g.:") - print(" ~/your/env/$ source bin/activate") - print(" ~/your/env/$ pip install wheel") - import_error = True - - try: - import twine - except ImportError as err: - print("\nError: %s" % err) - print("\nMaybe https://pypi.org/project/twine is not installed or virtualenv not activated?!?") - print("e.g.:") - print(" ~/your/env/$ source bin/activate") - print(" ~/your/env/$ pip install twine") - import_error = True - - if import_error: - sys.exit(-1) - - def verbose_check_output(*args): - """ 'verbose' version of subprocess.check_output() """ - call_info = "Call: %r" % " ".join(args) - try: - output = subprocess.check_output(args, universal_newlines=True, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as err: - print("\n***ERROR:") - print(err.output) - raise - return call_info, output - - def verbose_check_call(*args): - """ 'verbose' version of subprocess.check_call() """ - print("\tCall: %r\n" % " ".join(args)) - subprocess.check_call(args, universal_newlines=True) - - def confirm(txt): - print("\n%s" % txt) - if input("\nPublish anyhow? (Y/N)").lower() not in ("y", "j"): - print("Bye.") - sys.exit(-1) - - if "dev" in __version__: - confirm("WARNING: Version contains 'dev': v%s\n" % __version__) - - print("\nCheck if we are on 'master' branch:") - call_info, output = verbose_check_output("git", "branch", "--no-color") - print("\t%s" % call_info) - if "* master" in output: - print("OK") - else: - confirm("\nNOTE: It seems you are not on 'master':\n%s" % output) - - print("\ncheck if if git repro is clean:") - call_info, output = verbose_check_output("git", "status", "--porcelain") - print("\t%s" % call_info) - if output == "": - print("OK") - else: - print("\n *** ERROR: git repro not clean:") - print(output) - sys.exit(-1) - - print("\nRun './setup.py check':") - call_info, output = verbose_check_output("./setup.py", "check") - if "warning" in output: - print(output) - confirm("Warning found!") - else: - print("OK") - - print("\ncheck if pull is needed") - verbose_check_call("git", "fetch", "--all") - call_info, output = verbose_check_output("git", "log", "HEAD..origin/master", "--oneline") - print("\t%s" % call_info) - if output == "": - print("OK") - else: - print("\n *** ERROR: git repro is not up-to-date:") - print(output) - sys.exit(-1) - verbose_check_call("git", "push") - - print("\nCleanup old builds:") - def rmtree(path): - path = os.path.abspath(path) - if os.path.isdir(path): - print("\tremove tree:", path) - shutil.rmtree(path) - rmtree("./dist") - rmtree("./build") - - print("\nbuild but don't upload...") - log_filename="build.log" - with open(log_filename, "a") as log: - call_info, output = verbose_check_output( - sys.executable or "python", - "setup.py", "sdist", "bdist_wheel", "bdist_egg" - ) - print("\t%s" % call_info) - log.write(call_info) - log.write(output) - print("Build output is in log file: %r" % log_filename) - - git_tag="v%s" % __version__ - - print("\ncheck git tag") - call_info, output = verbose_check_output("git", "log", "HEAD..origin/master", "--oneline") - if git_tag in output: - print("\n *** ERROR: git tag %r already exists!" % git_tag) - print(output) - sys.exit(-1) - else: - print("OK") - - print("\nUpload with twine:") - twine_args = sys.argv[1:] - twine_args.remove("publish") - twine_args.insert(1, "dist/*") - print("\ttwine upload command args: %r" % " ".join(twine_args)) - from twine.commands.upload import main as twine_upload - twine_upload(twine_args) - - print("\ngit tag version") - verbose_check_call("git", "tag", git_tag) - - print("\ngit push tag to server") - verbose_check_call("git", "push", "--tags") - - sys.exit(0) - - -setup( - name='python-creole', - version=__version__, - description='python-creole is an open-source (GPL) markup converter in pure Python for: creole2html, html2creole, html2ReSt, html2textile', - long_description=long_description, - author=get_authors(), - author_email="python-creole@jensdiemer.de", - maintainer="Jens Diemer", - url='https://github.com/jedie/python-creole/', - packages=find_packages(), - include_package_data=True, # include package data under svn source control - data_files=[("", ["README.creole"])], # README used in unittest test_setup_utils.py - entry_points={ - "console_scripts": [ - "creole2html = creole.cmdline:cli_creole2html", - "html2creole = creole.cmdline:cli_html2creole", - "html2rest = creole.cmdline:cli_html2rest", - "html2textile = creole.cmdline:cli_html2textile", - ], - }, - tests_require=[ - "nose", # https://pypi.python.org/pypi/nose - ], - zip_safe=True, # http://packages.python.org/distribute/setuptools.html#setting-the-zip-safe-flag - 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.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "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", - ], - test_suite="nose.collector", -) @@ -0,0 +1,11 @@ +[tox] +isolated_build = True +envlist = py38,py37,py36 +skip_missing_interpreters = True + +[testenv] +whitelist_externals = make +commands = + make install + make pytest + |