diff --git a/Dockerfile b/Dockerfile index 08edfdf..afed4cb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,4 +2,4 @@ FROM python:3.6.6-alpine3.8 ARG VERSION -RUN pip3 install announcer==$VERSION +RUN pip3 install "announcer[tables]==$VERSION" diff --git a/announcer/changelogrenderer.py b/announcer/changelogrenderer.py index ae9815b..3c0cfc0 100644 --- a/announcer/changelogrenderer.py +++ b/announcer/changelogrenderer.py @@ -188,17 +188,70 @@ def analyse_listitem(self, token, depth, counter): log.debug("Listitem entries: %s", entries) return entries - def render_list_item(self, token): - return "list_item_uncalled" + def render_list_item(self, token): # pragma: no cover + """This function is not normally called.""" + return self.render_to_plaintext(token) def render_table(self, token): - return "table_unsupported" - - def render_table_row(self, token, is_header=False): - return "table_row_unsupported" + # Import classes for writing out the table if possible. + try: + from pytablewriter import UnicodeTableWriter as TableWriter + from pytablewriter.style import Style + except ImportError: + from collections import namedtuple + + class TableWriter: + def __init__(self): + self.headers = None + self.value_matrix = [] + self.column_styles = None + + def dumps(self): + lines = [] + if self.headers: + lines.append(" | ".join(self.headers)) + lines.extend(" | ".join(row) for row in self.value_matrix) + return "\n".join(lines) + + Style = namedtuple('Style', ['align']) + + # Get a writer object for dumping the table out. This can either be + writer = TableWriter() + + # If a header row was defined, add that to the table writer. + if hasattr(token, "header"): + writer.headers = self.analyse_table_row(token.header, is_header=True) + + # Add all the value rows. + writer.value_matrix = [ + self.analyse_table_row(table_row) + for table_row in token.children + ] + + # Add in any column alignment if defined. + if token.column_align != [None]: + alignment = { + None: "left", + 0: "center", + 1: "right" + } + writer.column_styles = [ + Style(align=alignment[col_alignment]) + for col_alignment in token.column_align + ] + + # Return the table in backticks to render it in fixed-width + return "```{0}```\n".format(writer.dumps()) + + def analyse_table_row(self, token, is_header=False): + return [self.render_table_cell(child, is_header) for child in token.children] + + def render_table_row(self, token, is_header=False): # pragma: no cover + """This function is not called in normal code.""" + return self.render_to_plaintext(token) def render_table_cell(self, token, in_header=False): - return "table_cell_unsupported" + return self.render_to_plaintext(token) @staticmethod def render_thematic_break(token): diff --git a/poetry.lock b/poetry.lock index 13dfe0c..d9b34eb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -97,7 +97,7 @@ version = "3.0.4" [[package]] category = "dev" description = "Cross-platform colored terminal text." -marker = "platform_system == \"Windows\" or sys_platform == \"win32\" or sys_platform == \"win32\" and python_version == \"3.4\"" +marker = "sys_platform == \"win32\" or platform_system == \"Windows\" or sys_platform == \"win32\" and python_version == \"3.4\"" name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" @@ -106,7 +106,7 @@ version = "0.4.1" [[package]] category = "dev" description = "Cross-platform colored terminal text." -marker = "platform_system == \"Windows\" or sys_platform == \"win32\" or sys_platform == \"win32\" and python_version != \"3.4\"" +marker = "sys_platform == \"win32\" or platform_system == \"Windows\" or sys_platform == \"win32\" and python_version != \"3.4\"" name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" @@ -131,6 +131,27 @@ version = "5.1" [package.extras] toml = ["toml"] +[[package]] +category = "main" +description = "Python library for extract property from data." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "dataproperty" +optional = true +python-versions = ">=3.5" +version = "0.49.1" + +[package.dependencies] +mbstrdecoder = ">=1.0.0,<2" +setuptools = ">=38.3.0" + +[package.dependencies.typepy] +extras = ["datetime"] +version = ">=1.1.1,<2" + +[package.extras] +logging = ["loguru (>=0.4.1,<1)"] +test = ["pytest", "pytest-md-report", "termcolor"] + [[package]] category = "dev" description = "Distribution utilities" @@ -185,7 +206,7 @@ description = "Python Git Library" name = "gitpython" optional = false python-versions = ">=3.4" -version = "3.1.2" +version = "3.1.3" [package.dependencies] gitdb = ">=4.0.1,<5" @@ -198,6 +219,14 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.8" +[[package]] +category = "main" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.9" + [[package]] category = "dev" description = "Read metadata from Python packages" @@ -214,6 +243,22 @@ zipp = ">=0.5" docs = ["sphinx", "rst.linker"] testing = ["packaging", "importlib-resources"] +[[package]] +category = "dev" +description = "Read metadata from Python packages" +marker = "python_version < \"3.8\"" +name = "importlib-metadata" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "1.6.0" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "rst.linker"] +testing = ["packaging", "importlib-resources"] + [[package]] category = "dev" description = "Read resources from Python packages" @@ -271,6 +316,21 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.4.3" +[[package]] +category = "main" +description = "multi-byte character string decoder" +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "mbstrdecoder" +optional = true +python-versions = ">=3.5" +version = "1.0.0" + +[package.dependencies] +chardet = ">=3.0.4,<4" + +[package.extras] +test = ["Faker (>=1.0.2)", "pytest"] + [[package]] category = "dev" description = "McCabe checker, plugin for flake8" @@ -303,7 +363,19 @@ marker = "python_version > \"2.7\"" name = "more-itertools" optional = false python-versions = ">=3.5" -version = "8.2.0" +version = "8.3.0" + +[[package]] +category = "main" +description = "msgfy is a Python library for convert Exception instance to a human-readable error message." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "msgfy" +optional = true +python-versions = ">=3.5" +version = "0.1.0" + +[package.extras] +test = ["pytest"] [[package]] category = "dev" @@ -340,7 +412,7 @@ description = "Core utilities for Python packages" name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.3" +version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" @@ -378,6 +450,18 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "0.8.0" +[[package]] +category = "main" +description = "pathvalidate is a Python library to sanitize/validate a string such as filenames/file-paths/etc." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "pathvalidate" +optional = true +python-versions = ">=3.5" +version = "2.3.0" + +[package.extras] +test = ["allpairspy", "click", "faker", "pytest"] + [[package]] category = "dev" description = "Python Build Reasonableness" @@ -440,6 +524,21 @@ colorama = "*" isort = ">=4.2.5,<5" mccabe = ">=0.6,<0.7" +[[package]] +category = "dev" +description = "python code static checker" +name = "pylint" +optional = false +python-versions = ">=3.5.*" +version = "2.5.2" + +[package.dependencies] +astroid = ">=2.4.0,<=2.5" +colorama = "*" +isort = ">=4.2.5,<5" +mccabe = ">=0.6,<0.7" +toml = ">=0.7.1" + [[package]] category = "dev" description = "Python parsing module" @@ -448,6 +547,43 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" version = "2.4.7" +[[package]] +category = "main" +description = "pytablewriter is a Python library to write a table in various formats: CSV / Elasticsearch / HTML / JavaScript / JSON / LaTeX / LDJSON / LTSV / Markdown / MediaWiki / NumPy / Excel / Pandas / Python / reStructuredText / SQLite / TOML / TSV / YAML." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "pytablewriter" +optional = true +python-versions = ">=3.5" +version = "0.54.0" + +[package.dependencies] +DataProperty = ">=0.49.1,<2" +mbstrdecoder = ">=1.0.0,<2" +msgfy = ">=0.1.0,<1" +pathvalidate = ">=2.3.0,<3" +setuptools = ">=38.3.0" +tabledata = ">=1.1.1,<2" +tcolorpy = ">=0.0.4,<1" + +[package.dependencies.typepy] +extras = ["datetime"] +version = ">=1.1.1,<2" + +[package.extras] +all = ["xlwt", "XlsxWriter (>=0.9.6,<2)", "elasticsearch (>=7.0.5,<8)", "pytablereader (>=0.30.0,<2)", "dominate (>=2.1.5,<3)", "loguru (>=0.4.1,<1)", "SimpleSQLite (>=1.1.1,<2)", "toml (>=0.9.3,<1)", "PyYAML (>=3.11,<6)", "simplejson (>=3.8.1,<4)"] +docs = ["sphinx-rtd-theme", "Sphinx (>=2.4)"] +es5 = ["elasticsearch (>=5.5.3,<6)"] +es6 = ["elasticsearch (>=6.3.1,<7)"] +es7 = ["elasticsearch (>=7.0.5,<8)"] +excel = ["xlwt", "XlsxWriter (>=0.9.6,<2)"] +from = ["pytablereader (>=0.30.0,<2)"] +html = ["dominate (>=2.1.5,<3)"] +logging = ["loguru (>=0.4.1,<1)"] +sqlite = ["SimpleSQLite (>=1.1.1,<2)"] +test = ["toml (>=0.9.3,<1)", "pytablereader (>=0.30.0,<2)", "PyYAML (>=3.11,<6)", "pytest", "tablib", "pytablereader (>=0.29)", "xlwt", "loguru (>=0.4.1,<1)", "termcolor", "SimpleSQLite (>=1.1.1,<2)", "simplejson (>=3.8.1,<4)", "XlsxWriter (>=0.9.6,<2)", "sqliteschema", "elasticsearch (>=7.0.5,<8)", "dominate (>=2.1.5,<3)"] +toml = ["toml (>=0.9.3,<1)"] +yaml = ["PyYAML (>=3.11,<6)"] + [[package]] category = "dev" description = "pytest: simple powerful testing with Python" @@ -503,6 +639,21 @@ pytest = ">=3.6" [package.extras] testing = ["fields", "hunter", "process-tests (2.0.2)", "six", "virtualenv"] +[[package]] +category = "dev" +description = "Pytest plugin for measuring coverage." +name = "pytest-cov" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.9.0" + +[package.dependencies] +coverage = ">=4.4" +pytest = ">=3.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests (2.0.2)", "six", "pytest-xdist", "virtualenv"] + [[package]] category = "dev" description = "pytest-httpserver is a httpserver for pytest" @@ -522,6 +673,27 @@ version = "*" dev = ["coverage", "ipdb", "pycodestyle", "pylint", "pytest", "pytest-cov", "reno", "requests", "rope", "sphinx", "sphinx-rtd-theme", "wheel"] test = ["coverage", "pytest", "pytest-cov", "requests"] +[[package]] +category = "main" +description = "Extensions to the standard Python datetime module" +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "python-dateutil" +optional = true +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "main" +description = "World timezone definitions, modern and historical" +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "pytz" +optional = true +python-versions = "*" +version = "2020.1" + [[package]] category = "dev" description = "YAML parser and emitter for Python" @@ -556,6 +728,24 @@ urllib3 = ">=1.21.1,<1.25" security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] +[[package]] +category = "main" +description = "Python HTTP for Humans." +name = "requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.23.0" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" +urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] + [[package]] category = "dev" description = "scandir, a better directory iterator and faster os.walk()" @@ -566,12 +756,12 @@ python-versions = "*" version = "1.10.0" [[package]] -category = "dev" +category = "main" description = "Python 2 and 3 compatibility utilities" name = "six" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.14.0" +version = "1.15.0" [[package]] category = "dev" @@ -593,13 +783,43 @@ version = "1.32.0" pbr = ">=2.0.0,<2.1.0 || >2.1.0" six = ">=1.10.0" +[[package]] +category = "main" +description = "tabledata is a Python library to represent tabular data. Used for pytablewriter/pytablereader/SimpleSQLite." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "tabledata" +optional = true +python-versions = ">=3.5" +version = "1.1.2" + +[package.dependencies] +DataProperty = ">=0.48.0,<2" +setuptools = ">=38.3.0" +typepy = ">=1.0.0,<2" + +[package.extras] +logging = ["loguru (>=0.4.1,<1)"] +test = ["pytablewriter (>=0.46)", "pytest"] + +[[package]] +category = "main" +description = "tcolopy is a Python library to apply true color for terminal text." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "tcolorpy" +optional = true +python-versions = ">=3.5" +version = "0.0.5" + +[package.extras] +test = ["pytest"] + [[package]] category = "dev" description = "Python Library for Tom's Obvious, Minimal Language" name = "toml" optional = false python-versions = "*" -version = "0.10.0" +version = "0.10.1" [[package]] category = "dev" @@ -626,6 +846,32 @@ version = ">=0.12,<1" docs = ["sphinx (>=2.0.0,<3)", "towncrier (>=18.5.0)", "pygments-github-lexers (>=0.0.5)", "sphinxcontrib-autoprogram (>=0.1.5)"] testing = ["freezegun (>=0.3.11,<1)", "pathlib2 (>=2.3.3,<3)", "pytest (>=4.0.0,<6)", "pytest-cov (>=2.5.1,<3)", "pytest-mock (>=1.10.0,<2)", "pytest-xdist (>=1.22.2,<2)", "pytest-randomly (>=1.2.3,<2)", "flaky (>=3.4.0,<4)", "psutil (>=5.6.1,<6)"] +[[package]] +category = "dev" +description = "tox is a generic virtualenv management and test command line tool" +name = "tox" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "3.15.1" + +[package.dependencies] +colorama = ">=0.4.1" +filelock = ">=3.0.0" +packaging = ">=14" +pluggy = ">=0.12.0" +py = ">=1.4.17" +six = ">=1.14.0" +toml = ">=0.9.4" +virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12,<2" + +[package.extras] +docs = ["sphinx (>=2.0.0)", "towncrier (>=18.5.0)", "pygments-github-lexers (>=0.0.5)", "sphinxcontrib-autoprogram (>=0.1.5)"] +testing = ["freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-xdist (>=1.22.2)", "pytest-randomly (>=1.0.0)", "flaky (>=3.4.0)", "psutil (>=5.6.1)"] + [[package]] category = "dev" description = "a fork of Python 2 and 3 ast modules with type comment support" @@ -634,6 +880,31 @@ optional = false python-versions = "*" version = "1.4.1" +[[package]] +category = "main" +description = "typepy is a Python library for variable type checker/validator/converter at a run time." +marker = "python_version >= \"3.5\" and python_version < \"4.0\"" +name = "typepy" +optional = true +python-versions = ">=3.5" +version = "1.1.1" + +[package.dependencies] +mbstrdecoder = ">=1.0.0,<2" +setuptools = ">=38.3.0" + +[package.dependencies.python-dateutil] +optional = true +version = ">=2.8.0,<3.0.0" + +[package.dependencies.pytz] +optional = true +version = ">=2018.9" + +[package.extras] +datetime = ["python-dateutil (>=2.8.0,<3.0.0)", "pytz (>=2018.9)"] +test = ["pytest", "termcolor", "python-dateutil (>=2.8.0,<3.0.0)", "pytz (>=2018.9)"] + [[package]] category = "main" description = "Type Hints for Python" @@ -667,13 +938,26 @@ version = "1.24.3" secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] +[[package]] +category = "main" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.9" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + [[package]] category = "dev" description = "Virtual Python Environment builder" name = "virtualenv" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "20.0.20" +version = "20.0.21" [package.dependencies] appdirs = ">=1.4.3,<2" @@ -695,11 +979,11 @@ testing = ["pytest (>=4)", "coverage (>=5)", "coverage-enable-subprocess (>=1)", [[package]] category = "dev" -description = "Measures number of Terminal column cells of wide-character codes" +description = "Measures the displayed width of unicode strings in a terminal" name = "wcwidth" optional = false python-versions = "*" -version = "0.1.9" +version = "0.2.2" [[package]] category = "dev" @@ -758,8 +1042,11 @@ version = "1.2.0" docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"] +[extras] +tables = ["pytablewriter"] + [metadata] -content-hash = "d56810edbf4fe445b0213c0108187c6302c378859a1e691b6c7d312751f04c8e" +content-hash = "252995a4d38e6c20034fddb8e7b1ce0ecaa5031eb595bb16845a3f12834ba3e8" python-versions = "^3.4" [metadata.files] @@ -864,6 +1151,10 @@ coverage = [ {file = "coverage-5.1-cp39-cp39-win_amd64.whl", hash = "sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e"}, {file = "coverage-5.1.tar.gz", hash = "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052"}, ] +dataproperty = [ + {file = "DataProperty-0.49.1-py3-none-any.whl", hash = "sha256:1c61f85450a6cffd15faccdeedc28ddd29d9ae95140b583e0aef15feb2c3d54d"}, + {file = "DataProperty-0.49.1.tar.gz", hash = "sha256:70ea253f74a51e39491770ac69428488bed75d62135accb234d89358d220b6ec"}, +] distlib = [ {file = "distlib-0.3.0.zip", hash = "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"}, ] @@ -880,16 +1171,20 @@ gitdb = [ {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"}, ] gitpython = [ - {file = "GitPython-3.1.2-py3-none-any.whl", hash = "sha256:da3b2cf819974789da34f95ac218ef99f515a928685db141327c09b73dd69c09"}, - {file = "GitPython-3.1.2.tar.gz", hash = "sha256:864a47472548f3ba716ca202e034c1900f197c0fb3a08f641c20c3cafd15ed94"}, + {file = "GitPython-3.1.3-py3-none-any.whl", hash = "sha256:ef1d60b01b5ce0040ad3ec20bc64f783362d41fa0822a2742d3586e1f49bb8ac"}, + {file = "GitPython-3.1.3.tar.gz", hash = "sha256:e107af4d873daed64648b4f4beb89f89f0cfbe3ef558fc7821ed2331c2f8da1a"}, ] idna = [ {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, + {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, + {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] importlib-metadata = [ {file = "importlib_metadata-0.23-py2.py3-none-any.whl", hash = "sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af"}, {file = "importlib_metadata-0.23.tar.gz", hash = "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26"}, + {file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"}, + {file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"}, ] importlib-resources = [ {file = "importlib_resources-1.0.2-py2.py3-none-any.whl", hash = "sha256:6e2783b2538bd5a14678284a3962b0660c715e5a0f10243fd5e00a4b5974f50b"}, @@ -924,6 +1219,10 @@ lazy-object-proxy = [ {file = "lazy_object_proxy-1.4.3-cp38-cp38-win32.whl", hash = "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd"}, {file = "lazy_object_proxy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239"}, ] +mbstrdecoder = [ + {file = "mbstrdecoder-1.0.0-py3-none-any.whl", hash = "sha256:a7cbc188b04937c92129c193a255ec91e8dfd8dd2e7e9bf04b61bc937ac86ad3"}, + {file = "mbstrdecoder-1.0.0.tar.gz", hash = "sha256:9df7778c0c051c98f6b5a848909202e5cd423c9692665b20d1a9bd0f771b8235"}, +] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -935,8 +1234,12 @@ mistletoe = [ more-itertools = [ {file = "more-itertools-7.2.0.tar.gz", hash = "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832"}, {file = "more_itertools-7.2.0-py3-none-any.whl", hash = "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"}, - {file = "more-itertools-8.2.0.tar.gz", hash = "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"}, - {file = "more_itertools-8.2.0-py3-none-any.whl", hash = "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c"}, + {file = "more-itertools-8.3.0.tar.gz", hash = "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be"}, + {file = "more_itertools-8.3.0-py3-none-any.whl", hash = "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982"}, +] +msgfy = [ + {file = "msgfy-0.1.0-py3-none-any.whl", hash = "sha256:ce8a8c8c223279fa0a2c0f278eec139fcf761ca4eb98f179f54a1b96f53514f5"}, + {file = "msgfy-0.1.0.tar.gz", hash = "sha256:474c08302cd56ccee1300ac7976a01ebd1e42716fc9bcd947d39a311a15b7012"}, ] mypy = [ {file = "mypy-0.720-cp35-cp35m-macosx_10_6_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:437020a39417e85e22ea8edcb709612903a9924209e10b3ec6d8c9f05b79f498"}, @@ -956,8 +1259,8 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] packaging = [ - {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, - {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, + {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, + {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, ] pathlib2 = [ {file = "pathlib2-2.3.5-py2.py3-none-any.whl", hash = "sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db"}, @@ -968,6 +1271,10 @@ pathspec = [ {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, ] +pathvalidate = [ + {file = "pathvalidate-2.3.0-py3-none-any.whl", hash = "sha256:1697c8ea71ff4c48e7aa0eda72fe4581404be8f41e51a17363ef682dd6824d35"}, + {file = "pathvalidate-2.3.0.tar.gz", hash = "sha256:32d30dbacb711c16bb188b12ce7e9a46b41785f50a12f64500f747480a4b6ee3"}, +] pbr = [ {file = "pbr-5.4.5-py2.py3-none-any.whl", hash = "sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8"}, {file = "pbr-5.4.5.tar.gz", hash = "sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c"}, @@ -991,11 +1298,17 @@ pyflakes = [ pylint = [ {file = "pylint-2.3.1-py3-none-any.whl", hash = "sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09"}, {file = "pylint-2.3.1.tar.gz", hash = "sha256:723e3db49555abaf9bf79dc474c6b9e2935ad82230b10c1138a71ea41ac0fff1"}, + {file = "pylint-2.5.2-py3-none-any.whl", hash = "sha256:dd506acce0427e9e08fb87274bcaa953d38b50a58207170dbf5b36cf3e16957b"}, + {file = "pylint-2.5.2.tar.gz", hash = "sha256:b95e31850f3af163c2283ed40432f053acbc8fc6eba6a069cb518d9dbf71848c"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] +pytablewriter = [ + {file = "pytablewriter-0.54.0-py3-none-any.whl", hash = "sha256:5aa600c2d404f5ad82e4fadf48814a2b8d6b5462da82464fee58a3415858f078"}, + {file = "pytablewriter-0.54.0.tar.gz", hash = "sha256:2d898a3eaf0b19aa0e48d9a9d1fe8db67f65235d6600d2b03817598991c917c4"}, +] pytest = [ {file = "pytest-4.6.10-py2.py3-none-any.whl", hash = "sha256:a24f6d11abff602da7b8aa33520734d604d25c4f070222e23667bb9782ba763e"}, {file = "pytest-4.6.10.tar.gz", hash = "sha256:0031b5021e1204f12e5a044500fbf31e3f64c6f2d69ded910af003abd0d91ae4"}, @@ -1003,11 +1316,21 @@ pytest = [ pytest-cov = [ {file = "pytest-cov-2.8.1.tar.gz", hash = "sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b"}, {file = "pytest_cov-2.8.1-py2.py3-none-any.whl", hash = "sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"}, + {file = "pytest-cov-2.9.0.tar.gz", hash = "sha256:b6a814b8ed6247bd81ff47f038511b57fe1ce7f4cc25b9106f1a4b106f1d9322"}, + {file = "pytest_cov-2.9.0-py2.py3-none-any.whl", hash = "sha256:c87dfd8465d865655a8213859f1b4749b43448b5fae465cb981e16d52a811424"}, ] pytest-httpserver = [ {file = "pytest_httpserver-0.3.4-py3-none-any.whl", hash = "sha256:7feab352b2626d1a0ecdebffcac5e5875979f08ad7e621b2289980ce8f6ebc5b"}, {file = "pytest_httpserver-0.3.4.tar.gz", hash = "sha256:c7269aed8b4f2d24e41eaa2034dd9ab7ae02b0cb6e71afeae93127832920ec8d"}, ] +python-dateutil = [ + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, +] +pytz = [ + {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, + {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, +] pyyaml = [ {file = "PyYAML-5.2-cp27-cp27m-win32.whl", hash = "sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc"}, {file = "PyYAML-5.2-cp27-cp27m-win_amd64.whl", hash = "sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4"}, @@ -1035,6 +1358,8 @@ pyyaml = [ requests = [ {file = "requests-2.21.0-py2.py3-none-any.whl", hash = "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"}, {file = "requests-2.21.0.tar.gz", hash = "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e"}, + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, ] scandir = [ {file = "scandir-1.10.0-cp27-cp27m-win32.whl", hash = "sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188"}, @@ -1050,8 +1375,8 @@ scandir = [ {file = "scandir-1.10.0.tar.gz", hash = "sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae"}, ] six = [ - {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, - {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] smmap = [ {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, @@ -1061,14 +1386,23 @@ stevedore = [ {file = "stevedore-1.32.0-py2.py3-none-any.whl", hash = "sha256:a4e7dc759fb0f2e3e2f7d8ffe2358c19d45b9b8297f393ef1256858d82f69c9b"}, {file = "stevedore-1.32.0.tar.gz", hash = "sha256:18afaf1d623af5950cc0f7e75e70f917784c73b652a34a12d90b309451b5500b"}, ] +tabledata = [ + {file = "tabledata-1.1.2-py3-none-any.whl", hash = "sha256:7d2019de87fd5da2f45f4e36fd2dd9da326dd3c3a3191b7b5bdb65a477b29dd5"}, + {file = "tabledata-1.1.2.tar.gz", hash = "sha256:db893596ab9066e5c4f002ae0fed70657e3b75cceb52dd1de5a0e145e338d830"}, +] +tcolorpy = [ + {file = "tcolorpy-0.0.5-py3-none-any.whl", hash = "sha256:aeed3bed7faac29a6529be7e0e0ad77ac68d8353e9a03ca18ffd2ea1d9e1d6df"}, + {file = "tcolorpy-0.0.5.tar.gz", hash = "sha256:6215a0db797c7520a7ac7833da91595ddd30b6743314096fe6c890d1b91ac228"}, +] toml = [ - {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, - {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, - {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, + {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, + {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, ] tox = [ {file = "tox-3.14.0-py2.py3-none-any.whl", hash = "sha256:0bc216b6a2e6afe764476b4a07edf2c1dab99ed82bb146a1130b2e828f5bff5e"}, {file = "tox-3.14.0.tar.gz", hash = "sha256:c4f6b319c20ba4913dbfe71ebfd14ff95d1853c4231493608182f66e566ecfe1"}, + {file = "tox-3.15.1-py2.py3-none-any.whl", hash = "sha256:322dfdf007d7d53323f767badcb068a5cfa7c44d8aabb698d131b28cf44e62c4"}, + {file = "tox-3.15.1.tar.gz", hash = "sha256:8c9ad9b48659d291c5bc78bcabaa4d680d627687154b812fa52baedaa94f9f83"}, ] typed-ast = [ {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, @@ -1093,6 +1427,10 @@ typed-ast = [ {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, ] +typepy = [ + {file = "typepy-1.1.1-py3-none-any.whl", hash = "sha256:418e24c44cf5fc260c2e2bbc68a3d0bc8c43f488412663c7ce1f33efa5133323"}, + {file = "typepy-1.1.1.tar.gz", hash = "sha256:a0850559dfd135577c6d565c0268fcad1327cab9c4c295015d4d882aa9a24786"}, +] typing = [ {file = "typing-3.7.4.1-py2-none-any.whl", hash = "sha256:c8cabb5ab8945cd2f54917be357d134db9cc1eb039e59d1606dc1e60cb1d9d36"}, {file = "typing-3.7.4.1-py3-none-any.whl", hash = "sha256:f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714"}, @@ -1106,14 +1444,16 @@ typing-extensions = [ urllib3 = [ {file = "urllib3-1.24.3-py2.py3-none-any.whl", hash = "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"}, {file = "urllib3-1.24.3.tar.gz", hash = "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4"}, + {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, + {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, ] virtualenv = [ - {file = "virtualenv-20.0.20-py2.py3-none-any.whl", hash = "sha256:b4c14d4d73a0c23db267095383c4276ef60e161f94fde0427f2f21a0132dde74"}, - {file = "virtualenv-20.0.20.tar.gz", hash = "sha256:fd0e54dec8ac96c1c7c87daba85f0a59a7c37fe38748e154306ca21c73244637"}, + {file = "virtualenv-20.0.21-py2.py3-none-any.whl", hash = "sha256:a730548b27366c5e6cbdf6f97406d861cccece2e22275e8e1a757aeff5e00c70"}, + {file = "virtualenv-20.0.21.tar.gz", hash = "sha256:a116629d4e7f4d03433b8afa27f43deba09d48bc48f5ecefa4f015a178efb6cf"}, ] wcwidth = [ - {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, - {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, + {file = "wcwidth-0.2.2-py2.py3-none-any.whl", hash = "sha256:b651b6b081476420e4e9ae61239ac4c1b49d0c5ace42b2e81dc2ff49ed50c566"}, + {file = "wcwidth-0.2.2.tar.gz", hash = "sha256:3de2e41158cb650b91f9654cbf9a3e053cee0719c9df4ddc11e4b568669e9829"}, ] werkzeug = [ {file = "Werkzeug-0.16.1-py2.py3-none-any.whl", hash = "sha256:1e0dedc2acb1f46827daa2e399c1485c8fa17c0d8e70b6b875b4e7f54bf408d2"}, diff --git a/pyproject.toml b/pyproject.toml index 3880246..57bbe4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,10 @@ python = "^3.4" requests = "^2.19" mistletoe = "^0.7.1" typing = "^3.6.4" +pytablewriter = { version = "^0.54.0", python = "^3.5", optional = true } + +[tool.poetry.extras] +tables = ["pytablewriter"] [tool.poetry.dev-dependencies] pylint = "^2.3" diff --git a/tests/test_changelog.py b/tests/test_changelog.py index e9be8d5..736f52b 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -38,3 +38,48 @@ def test_changelog_formatting(): "alert(s);\n" "```\n" "2. List that starts at 2\n") + + +def test_changelog_tables(): + cl = announcer.Changelog(os.path.join(TEST_DIR, "testchangelog_tables.md")) + (details, diff_url) = cl.get_version_details("0.1.0") + + try: + from pytablewriter import UnicodeTableWriter as TableWriter + from pytablewriter.style import Style + + # We have access to pytablewriter, so use Unicode table + assert details == ( + u"0.1.0 - 2020-06-02\n" + "*Tested*\n" + "```" + "\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500" + "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c" + "\u2500\u2500\u2500\u2500\u2500\u2510\n" + "\u2502 Tables \u2502 Are \u2502Cool \u2502\n" + "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500" + "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c" + "\u2500\u2500\u2500\u2500\u2500\u2524\n" + "\u2502col 1 is\u2502left-aligned \u2502$1600\u2502\n" + "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500" + "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c" + "\u2500\u2500\u2500\u2500\u2500\u2524\n" + "\u2502col 2 is\u2502 centered \u2502 $12\u2502\n" + "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500" + "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c" + "\u2500\u2500\u2500\u2500\u2500\u2524\n" + "\u2502col 3 is\u2502right-aligned\u2502 $1\u2502\n" + "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500" + "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534" + "\u2500\u2500\u2500\u2500\u2500\u2518\n" + "```\n" + "Next line") + except ImportError: + # No access to TableWriter, so use the other style of table. + assert details == (u"0.1.0 - 2020-06-02\n" + "*Tested*\n" + "```Tables | Are | Cool\n" + "col 1 is | left-aligned | $1600\n" + "col 2 is | centered | $12\n" + "col 3 is | right-aligned | $1```\n" + "Next line") diff --git a/tests/testchangelog_tables.md b/tests/testchangelog_tables.md new file mode 100644 index 0000000..8a1ccc1 --- /dev/null +++ b/tests/testchangelog_tables.md @@ -0,0 +1,11 @@ +# Changelog +## [0.1.0] - 2020-06-02 +### Tested +| Tables | Are | Cool | +|----------|:-------------:|------:| +| col 1 is | left-aligned | $1600 | +| col 2 is | centered | $12 | +| col 3 is | right-aligned | $1 | +Next line + +[0.1.0]: https://github.com/Metaswitch/announcer/tree/0.1.0 diff --git a/tox.ini b/tox.ini index 6205efd..e42f1cc 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,13 @@ commands = poetry install -v poetry run pytest tests/ +[testenv:py36] +whitelist_externals = poetry +skip_install = true +commands = + poetry install -v -E tables + poetry run pytest tests/ + [testenv:flake8] whitelist_externals = poetry skip_install = true @@ -42,3 +49,9 @@ skip_install = true commands = poetry install -v poetry run pytest --cov=announcer tests + +[coverage:report] +# Regexes for lines to exclude from consideration +exclude_lines = + pragma: no cover + except ImportError: \ No newline at end of file