From be8270a4c9a9510c4f22c6c02c3887a367926a46 Mon Sep 17 00:00:00 2001 From: cclauss Date: Wed, 25 Sep 2019 12:43:32 +0200 Subject: [PATCH 1/3] Cleanup to prepare for a release --- .travis.yml | 1 + Pipfile | 2 +- Pipfile.lock | 60 ------------------------------------------ README.md | 20 ++++++++++++++ README.rst | 14 ---------- setup.cfg | 2 -- setup.py | 54 ++++++++++++++++++------------------- tap2junit/__main__.py | 45 ++++++++++++++++++++----------- tap2junit/tap13.py | 55 +++++++++++++++++++++++++------------- test/output/.empty | 0 test/output/.gitignore | 2 -- 11 files changed, 112 insertions(+), 143 deletions(-) delete mode 100644 Pipfile.lock create mode 100644 README.md delete mode 100644 README.rst delete mode 100644 setup.cfg create mode 100644 test/output/.empty delete mode 100644 test/output/.gitignore diff --git a/.travis.yml b/.travis.yml index 2db6b99..2551482 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,5 +12,6 @@ env: install: pip install flake8 junit-xml yamlish before_script: flake8 . --count --select=E9,F --show-source --statistics script: + - python tap2junit/tap13.py - python -m tap2junit -i test/fixtures/${FILENAME}.tap -o test/output/${FILENAME}.xml - cat test/output/${FILENAME}.xml diff --git a/Pipfile b/Pipfile index ee8f0c9..12214ca 100644 --- a/Pipfile +++ b/Pipfile @@ -4,8 +4,8 @@ verify_ssl = true name = "pypi" [packages] -yamlish = "*" junit-xml = "*" +yamlish = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index b5a7b34..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,60 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "a025909c585710aa9621fec0bb4754383aa58840d1b004044a7b2f39f87cfe60" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "2.7" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "junit-xml": { - "hashes": [ - "sha256:602f1c480a19d64edb452bf7632f76b5f2cb92c1938c6e071dcda8ff9541dc21" - ], - "index": "pypi", - "version": "==1.8" - }, - "pyyaml": { - "hashes": [ - "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", - "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", - "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", - "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", - "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", - "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", - "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", - "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", - "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", - "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", - "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" - ], - "version": "==3.13" - }, - "six": { - "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" - ], - "version": "==1.11.0" - }, - "yamlish": { - "hashes": [ - "sha256:8a87c9f29c508152ef92246adbc79eb3a34214d6bcc59fc33298c07cff4e1f94", - "sha256:a56624e6c6f7257760a10578dd804baa3af3ed0edc08f9a0074dc82b44dc4725", - "sha256:c08b243b4d39a456948859f193825f6665e84e5393f89c398e6d3140cfc06f54" - ], - "index": "pypi", - "version": "==0.18.1" - } - }, - "develop": {} -} diff --git a/README.md b/README.md new file mode 100644 index 0000000..387b83d --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +A utility that converts [TAP version 13](https://testanything.org/) to [JUnit](https://junit.org/junit5/). That's it. + +The syntax expected is currently pretty custom-tailored for use at https://ci.nodejs.org. + +Improvements welcome. + +To install: + +`pip install tap2junit` + +To run: + +`tap2junit -i file.tap -o file.xml` + +Suggested code hygiene: +``` +$ flake8 --max-line-length=88 . +$ isort -rc . +$ black . +``` \ No newline at end of file diff --git a/README.rst b/README.rst deleted file mode 100644 index 1dad75a..0000000 --- a/README.rst +++ /dev/null @@ -1,14 +0,0 @@ -A utility that converts tap13 to jUnit. That's it. - -The syntax expected is pretty custom-tailored at the moment for use at -https://ci.nodejs.org. - -Improvements welcome. - -To install: - -``pip install tap2junit`` - -To Run: - -``tap2junit -i file.tap -o file.xml`` diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 5aef279..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -description-file = README.rst diff --git a/setup.py b/setup.py index 20808d6..1a7f60c 100644 --- a/setup.py +++ b/setup.py @@ -1,39 +1,35 @@ -# coding: utf-8 - -# Always prefer setuptools over distutils -from setuptools import setup -# To use a consistent encoding -from codecs import open from os import path +import setuptools + here = path.abspath(path.dirname(__file__)) # Get the long description from the README file -with open(path.join(here, 'README.rst'), encoding='utf-8') as f: - long_description = f.read() +with open(path.join(here, "README.md")) as in_file: + long_description = in_file.read() -setup( - name='tap2junit', - version='0.1.5', - description='Tap13 to jUnit', +setuptools.setup( + name="tap2junit", + version="0.1.5", + description="Tap13 to jUnit", long_description=long_description, - url='https://github.com/jbergstroem/tap2junit', - author='Johan Bergström', - author_email='bugs@bergtroem.nu', + url="https://github.com/nodejs/tap2junit", + author="Node.js contributors", + author_email="cclauss@me.com", classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Build Tools', - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 3', + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Topic :: Software Development :: Build Tools", ], - keywords='tap13 junit', - packages=['tap2junit'], - install_requires=['yamlish', 'junit-xml'], - entry_points={ - 'console_scripts': [ - 'tap2junit = tap2junit.__main__:main', - ], - }, + keywords="tap13 junit", + packages=["tap2junit"], + install_requires=["junit-xml", "yamlish"], + entry_points={"console_scripts": ["tap2junit = tap2junit.__main__:main"]}, ) diff --git a/tap2junit/__main__.py b/tap2junit/__main__.py index 04a8e65..bdfc54e 100644 --- a/tap2junit/__main__.py +++ b/tap2junit/__main__.py @@ -1,27 +1,28 @@ import argparse import os import platform -from junit_xml import TestSuite, TestCase + +from junit_xml import TestCase, TestSuite from tap2junit.tap13 import TAP13 as tap13 def map_yaml_to_junit(test): yaml = test.yaml or {} # Even though the name is `duration_ms` the value is in seconds. - elapsed_sec = yaml.get('duration_ms', None) + elapsed_sec = yaml.get("duration_ms", None) t = TestCase(test.description, classname=None, elapsed_sec=elapsed_sec) - if test.result == 'ok': - if test.directive in ['SKIP', 'TODO']: + if test.result == "ok": + if test.directive in ("SKIP", "TODO"): t.add_skipped_info(test.comment) else: t.stdout = test.comment - elif test.result == 'not ok': - err_code = yaml.get('exitcode', 0) - err_severity = yaml.get('severity', '') - err_output = yaml.get('stack', '') + elif test.result == "not ok": + err_code = yaml.get("exitcode", 0) + err_severity = yaml.get("severity", "") + err_output = yaml.get("stack", "") error_message = "{} ({})".format(err_severity, err_code) - if err_severity == 'crashed' or err_code < 0: + if err_code < 0 or err_severity == "crashed": t.add_error_info(error_message, err_output, err_code) else: t.add_failure_info(error_message, err_output, err_code) @@ -40,16 +41,28 @@ def convert(in_file, out_file): input_file = os.path.splitext(in_file.name)[0] data = in_file.read() result = parse(input_file, data) - TestSuite.to_file(out_file, [result], prettyprint=True, encoding='utf-8') + TestSuite.to_file(out_file, [result], prettyprint=True, encoding="utf-8") def main(): - arg_parser = argparse.ArgumentParser('tap2junit') - arg_parser.add_argument('--input', '-i', type=argparse.FileType('r'), help='path to tap13 file', required=True) - arg_parser.add_argument('--output', '-o', type=argparse.FileType('w'), help='output file name', required=True) - args = arg_parser.parse_args() - convert(args.input, args.output) + arg_parser = argparse.ArgumentParser("tap2junit") + arg_parser.add_argument( + "--input", + "-i", + type=argparse.FileType("r"), + help="path to tap13 file", + required=True, + ) + arg_parser.add_argument( + "--output", + "-o", + type=argparse.FileType("w"), + help="output file name", + required=True, + ) + args = arg_parser.parse_args() + convert(args.input, args.output) if __name__ == "__main__": - main() + main() diff --git a/tap2junit/tap13.py b/tap2junit/tap13.py index df6535b..b1a08e2 100644 --- a/tap2junit/tap13.py +++ b/tap2junit/tap13.py @@ -1,4 +1,3 @@ -from __future__ import print_function # Copyright 2013, Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify @@ -20,12 +19,14 @@ from __future__ import print_function import re + +import yamlish + try: from StringIO import StringIO except ImportError: from io import StringIO - -import yamlish + try: basestring @@ -34,15 +35,23 @@ RE_VERSION = re.compile(r"^\s*TAP version 13\s*$") -RE_PLAN = re.compile(r"^\s*(?P\d+)\.\.(?P\d+)\s*(#\s*(?P.*))?\s*$") -RE_TEST_LINE = re.compile(r"^\s*(?P(not\s+)?ok)\s*(?P\d+)?\s*(?P[^#]+)?\s*(#\s*(?PTODO|SKIP)?\s*(?P.+)?)?\s*$", re.IGNORECASE) +RE_PLAN = re.compile( + r"^\s*(?P\d+)\.\.(?P\d+)\s*(#\s*(?P.*))?\s*$" +) +RE_TEST_LINE = re.compile( + ( + r"^\s*(?P(not\s+)?ok)\s*(?P\d+)?\s*(?P[^#]+)" + r"?\s*(#\s*(?PTODO|SKIP)?\s*(?P.+)?)?\s*$" + ), + re.IGNORECASE, +) RE_EXPLANATION = re.compile(r"^\s*#\s*(?P.+)?\s*$") RE_YAMLISH_START = re.compile(r"^\s*---.*$") RE_YAMLISH_END = re.compile(r"^\s*\.\.\.\s*$") class Test(object): - def __init__(self, result, id, description = None, directive = None, comment = None): + def __init__(self, result, id, description=None, directive=None, comment=None): self.result = result self.id = id self.description = description @@ -62,7 +71,6 @@ def __init__(self): self.__tests_counter = 0 self.tests_planned = None - def _parse(self, source): seek_version = True seek_plan = False @@ -116,11 +124,11 @@ def _parse(self, source): m = RE_PLAN.match(line) if m: d = m.groupdict() - self.tests_planned = int(d.get('end', 0)) + self.tests_planned = int(d.get("end", 0)) seek_plan = False # Stop processing if tests were found before the plan - # if plan is at the end, it must be the last line -> stop processing + # if plan is at the end, it must be last line -> stop processing if self.__tests_counter > 0: break @@ -129,15 +137,22 @@ def _parse(self, source): if m: self.__tests_counter += 1 t_attrs = m.groupdict() - if t_attrs['id'] is None: - t_attrs['id'] = self.__tests_counter - t_attrs['id'] = int(t_attrs['id']) - if t_attrs['id'] < self.__tests_counter: + if t_attrs["id"] is None: + t_attrs["id"] = self.__tests_counter + t_attrs["id"] = int(t_attrs["id"]) + if t_attrs["id"] < self.__tests_counter: raise ValueError("Descending test id on line: %r" % line) - # according to TAP13 specs, missing tests must be handled as 'not ok' - # here we add the missing tests in sequence - while t_attrs['id'] > self.__tests_counter: - self.tests.append(Test('not ok', self.__tests_counter, comment = 'DIAG: Test %s not present' % self.__tests_counter)) + # according to TAP13 specs, missing tests must be handled as + # 'not ok'. Here we add the missing tests in sequence + while t_attrs["id"] > self.__tests_counter: + self.tests.append( + Test( + "not ok", + self.__tests_counter, + comment="DIAG: Test %s not present" + % self.__tests_counter, + ) + ) self.__tests_counter += 1 t = Test(**t_attrs) self.tests.append(t) @@ -150,8 +165,9 @@ def _parse(self, source): if len(self.tests) != self.tests_planned: for i in range(len(self.tests), self.tests_planned): - self.tests.append(Test('not ok', i+1, comment = 'DIAG: Test %s not present')) - + self.tests.append( + Test("not ok", i + 1, comment="DIAG: Test %s not present") + ) def parse(self, source): if isinstance(source, basestring): @@ -199,6 +215,7 @@ def parse(self, source): t.parse(input) import pprint + for test in t.tests: print(test.result, test.id, test.description, "#", test.directive, test.comment) pprint.pprint(test.yaml_buffer) diff --git a/test/output/.empty b/test/output/.empty new file mode 100644 index 0000000..e69de29 diff --git a/test/output/.gitignore b/test/output/.gitignore deleted file mode 100644 index f4c3747..0000000 --- a/test/output/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/* -!.gitignore \ No newline at end of file From a7a4eeadebdfee6a6e8d929b9e4c2adfb50c2141 Mon Sep 17 00:00:00 2001 From: cclauss Date: Thu, 26 Sep 2019 01:31:13 +0200 Subject: [PATCH 2/3] rm test/fixtures/test2.xml --- test/fixtures/test2.xml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test/fixtures/test2.xml diff --git a/test/fixtures/test2.xml b/test/fixtures/test2.xml deleted file mode 100644 index 0762b98..0000000 --- a/test/fixtures/test2.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 1f04dca004742b6e6f063a207bbf35887cd22e09 Mon Sep 17 00:00:00 2001 From: cclauss Date: Thu, 26 Sep 2019 11:17:39 +0200 Subject: [PATCH 3/3] fixup: re-GPL --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1a7f60c..35a43a6 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3",