summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJensDiemer <git@jensdiemer.de>2020-01-29 14:16:15 +0100
committerJensDiemer <git@jensdiemer.de>2020-02-01 13:22:09 +0100
commit67c192d8e852979fae9d264b32e86a5de63b3318 (patch)
tree7721735702f853703c149c1c82ff24db7937b71d
parent5c2ac71e9f92692dfcd152b8b449c7775bda9319 (diff)
downloadcreole-67c192d8e852979fae9d264b32e86a5de63b3318.tar.gz
Helper to build and upload to PyPi, with prechecks and update README.rst from README.creole
-rw-r--r--.gitignore4
-rw-r--r--creole/__init__.py11
-rw-r--r--creole/setup_utils.py254
-rw-r--r--pyproject.toml12
4 files changed, 238 insertions, 43 deletions
diff --git a/.gitignore b/.gitignore
index 3d914c2..9d54f44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,9 +4,13 @@
*.egg-info
/dist
/build
+/publish.log
.idea
/poetry.lock
/.coverage
.tox
+
+# Will be generated from README.creole and added to sdist
+/README.rst
diff --git a/creole/__init__.py b/creole/__init__.py
index 25dd09c..e5d6324 100644
--- a/creole/__init__.py
+++ b/creole/__init__.py
@@ -1,18 +1,13 @@
-# coding: utf-8
-
"""
python-creole
~~~~~~~~~~~~~
- :homepage:
- http://code.google.com/p/python-creole/
-
:sourcecode:
- http://github.com/jedie/python-creole
+ https://github.com/jedie/python-creole
:PyPi:
- http://pypi.python.org/pypi/python-creole/
+ https://pypi.org/project/python-creole/
:copyleft: 2008-2020 by python-creole team, see AUTHORS for more details.
:license: GNU GPL v3 or above, see LICENSE for more details.
@@ -28,7 +23,7 @@ from creole.emitter.html2textile_emitter import TextileEmitter
from creole.parser.creol2html_parser import CreoleParser
from creole.parser.html_parser import HtmlParser
-__version__ = "1.4.1"
+__version__ = "1.4.2.dev1"
__api__ = "1.0" # Creole 1.0 spec - http://wikicreole.org/
VERSION_STRING = __version__ # remove in future
diff --git a/creole/setup_utils.py b/creole/setup_utils.py
index 17623f5..c45e194 100644
--- a/creole/setup_utils.py
+++ b/creole/setup_utils.py
@@ -1,5 +1,3 @@
-# coding: utf-8
-
"""
utils for distutils setup
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -23,9 +21,9 @@
try:
from creole.setup_utils import get_long_description
except ImportError:
- if "register" in sys.argv or "sdist" in sys.argv or "--long-description" in sys.argv:
+ if 'register' in sys.argv or 'sdist' in sys.argv or '--long-description' in sys.argv:
etype, evalue, etb = sys.exc_info()
- evalue = etype("%s - Please install python-creole >= v0.8 - e.g.: pip install python-creole" % evalue)
+ evalue = etype('%s - Please install python-creole >= v0.8 - e.g.: pip install python-creole' % evalue)
raise etype, evalue, etb
long_description = None
else:
@@ -44,15 +42,18 @@
import codecs
import os
+import shutil
+import subprocess
import sys
import warnings
+from pathlib import Path
-from creole import creole2html, html2rest
+from creole import __version__, creole2html, html2rest
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',
)
@@ -70,13 +71,16 @@ def should_raise_errors():
return False
-def get_long_description(package_root, filename="README.creole", raise_errors=None):
+def get_long_description(package_root, filename='README.creole', raise_errors=None):
""" read README file and convert it on-the-fly to ReStructuredText. """
+
+ warnings.warn('get_long_description() will be removed in the future', DeprecationWarning)
+
if raise_errors is None:
raise_errors = should_raise_errors()
if raise_errors:
- sys.stderr.write("Test creole2rest and raise an error, if rendering failed...\n")
+ sys.stderr.write('Test creole2rest and raise an error, if rendering failed...\n')
# raise a error if a unknown node found
unknown_emit = raise_unknown_node
else:
@@ -84,10 +88,10 @@ def get_long_description(package_root, filename="README.creole", raise_errors=No
unknown_emit = transparent_unknown_nodes
filepath = os.path.join(package_root, filename)
- long_description_origin = ""
+ long_description_origin = ''
try:
# Read creole README
- f = codecs.open(filepath, "r", encoding="utf-8")
+ f = codecs.open(filepath, 'r', encoding='utf-8')
long_description_origin = f.read().strip()
f.close()
@@ -97,14 +101,14 @@ def get_long_description(package_root, filename="README.creole", raise_errors=No
# convert html to ReSt
long_description_rest = html2rest(
long_description_html,
- emitter_kwargs={"unknown_emit": unknown_emit}
+ emitter_kwargs={'unknown_emit': unknown_emit}
)
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 = f"[Error: {evalue}]\n{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.
@@ -112,31 +116,225 @@ def get_long_description(package_root, filename="README.creole", raise_errors=No
try:
pypi_rest2html(long_description_rest)
except SystemExit as e:
- msg = f"Error creole2rest self test failed: rest2html() exist with status code: {e.args[0]}\n"
+ 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(f"ReSt2html error: {e}")
+ sys.exit(f'ReSt2html error: {e}')
else:
- if "check" in sys.argv:
- print("Generating creole to ReSt to html, ok.")
+ if 'check' in sys.argv:
+ print('Generating creole to ReSt to html, ok.')
return long_description_rest
-def _get_long_description(*args, **kwargs):
- msg = "'GetLongDescription' is deprecated, use 'get_long_description' instead."
- if should_raise_errors():
- raise DeprecationWarning(msg)
+def update_rst_readme(package_root, filename='README.creole'):
+ """
+ Generate README.rst from README.creole
+ """
+ assert isinstance(package_root, Path)
+ assert package_root.is_dir(), f'Directory not found: {package_root}'
+ creole_readme_path = Path(package_root, filename)
+ assert creole_readme_path.is_file(), f'File not found: {creole_readme_path}'
+
+ rest_readme_path = creole_readme_path.with_suffix('.rst')
+ print(
+ f'Generate {rest_readme_path.name} from {creole_readme_path.name}',
+ end='...', flush=True
+ )
+
+ with creole_readme_path.open('r') as f:
+ creole_readme = f.read().strip()
+
+ # convert creole into html
+ html_readme = creole2html(creole_readme)
+
+ # convert html to ReSt
+ rest_readme = html2rest(
+ html_readme,
+ emitter_kwargs={
+ 'unknown_emit': raise_unknown_node # raise a error if a unknown node found
+ }
+ )
+
+ with rest_readme_path.open('w') as f:
+ f.write(rest_readme)
+
+ print('done.')
+
+
+def update_creole_rst_readme():
+ update_rst_readme(
+ package_root=Path(__file__).parent.parent,
+ filename='README.creole'
+ )
+
+
+def verbose_check_output(*args, log=None):
+ """ '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)
+ if log is not None:
+ log.write(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(f'\n{txt}')
+ if input('\nPublish anyhow? (Y/N)').lower() not in ('y', 'j'):
+ print('Bye.')
+ sys.exit(-1)
+
+
+def poetry_publish(package_root, version, filename='README.creole', log_filename='publish.log'):
+ """
+ Helper to build and upload to PyPi, with prechecks and update README.rst from README.creole
+
+ Optional arguments are passed to `poetry publish` e.g.:
+
+ $ poetry config repositories.testpypi https://test.pypi.org/simple
+ $ poetry run publish --repository=testpypi
+
+ 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 'poetry', 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
+
+ add this to poetry pyproject.toml, e.g.:
+
+ [tool.poetry.scripts]
+ publish = 'foo.bar:publish'
+
+ based on:
+ https://github.com/jedie/python-code-snippets/blob/master/CodeSnippets/setup_publish.py
+ """
+ update_rst_readme(package_root=package_root, filename=filename)
+
+ for key in ('dev', 'rc'):
+ if key in version:
+ confirm(f'WARNING: Version contains {key!r}: v{version}\n')
+ break
+
+ print('\nCheck if we are on "master" branch:')
+ call_info, output = verbose_check_output('git', 'branch', '--no-color')
+ print(f'\t{call_info}')
+ if '* master' in output:
+ print('OK')
+ else:
+ confirm(f'\nNOTE: It seems you are not on "master":\n{output}')
+
+ print('\ncheck if if git repro is clean:')
+ call_info, output = verbose_check_output('git', 'status', '--porcelain')
+ print(f'\t{call_info}')
+ if output == '':
+ print('OK')
+ else:
+ print('\n *** ERROR: git repro not clean:')
+ print(output)
+ sys.exit(-1)
+
+ print('\nRun "poetry check":')
+ call_info, output = verbose_check_output('poetry', 'check')
+ if 'All set!' not in output:
+ print(output)
+ confirm('Check failed!')
+ 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(f'\t{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(f'\nSet new version to: v{version}')
+ verbose_check_call('poetry', 'version', version)
+
+ print('\nbuild but do not upload...')
+
+ with open(log_filename, 'a') as log:
+ log.write('\n')
+ log.write('-' * 100)
+ log.write('\n')
+ call_info, output = verbose_check_output('poetry', 'build', log=log)
+ print(f'\t{call_info}')
+ log.write(call_info)
+ log.write(output)
+
+ print(f'Build log file is here: {log_filename!r}')
+
+ git_tag = f'v{version}'
+
+ print('\ncheck git tag')
+ call_info, output = verbose_check_output(
+ 'git', 'log', 'HEAD..origin/master', '--oneline',
+ )
+ if git_tag in output:
+ print(f'\n *** ERROR: git tag {git_tag!r} already exists!')
+ print(output)
+ sys.exit(-1)
else:
- warnings.warn(msg, DeprecationWarning)
- return get_long_description(*args, **kwargs)
+ print('OK')
+ print('\nUpload to PyPi via poetry:')
+ args = ['poetry', 'publish'] + sys.argv[1:]
+ verbose_check_call(*args)
-GetLongDescription = _get_long_description # for backward-compatibility
+ 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)
+
+
+def publish_python_creole():
+ """
+ Publish python-creole to PyPi
+ Call this via:
+ $ poetry run publish
+ """
+ poetry_publish(
+ package_root=Path(__file__).parent.parent,
+ version=__version__,
+ )
-if __name__ == "__main__":
- package_root = os.path.abspath("../")
- long_description = get_long_description(package_root)
- print(long_description)
+if __name__ == '__main__':
+ update_creole_rst_readme()
diff --git a/pyproject.toml b/pyproject.toml
index b821124..cb88369 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,14 +1,10 @@
[tool.poetry]
name = 'python-creole'
-version = '1.4.1'
+version = "1.4.2.dev1"
description = 'python-creole is an open-source (GPL) markup converter in pure Python for: creole2html, html2creole, html2ReSt, html2textile'
-# TODO: convert it:
-readme='README.creole'
-
-# on the way, see: https://github.com/python-poetry/poetry/pull/1166/
-# https://packaging.python.org/guides/making-a-pypi-friendly-readme/#including-your-readme-in-your-package-s-metadata
-# long_description_content_type = 'text/plain'
+# Will be generated from README.creole with: 'poetry run update_rst_readme'
+readme='README.rst'
license = 'GPL-3.0-or-later'
authors = ['Jens Diemer <python-creole@jensdiemer.de>']
@@ -57,6 +53,8 @@ creole2html = 'creole.cmdline:cli_creole2html'
html2creole = 'creole.cmdline:cli_html2creole'
html2rest = 'creole.cmdline:cli_html2rest'
html2textile = 'creole.cmdline:cli_html2textile'
+update_rst_readme = 'creole.setup_utils:update_creole_rst_readme'
+publish = 'creole.setup_utils:publish_python_creole'
[build-system]
requires = ['poetry>=0.12']