From 53b73af52fca1d254442e9303d20586e2bb91f15 Mon Sep 17 00:00:00 2001 From: David Halls Date: Thu, 19 Oct 2017 22:07:21 +0100 Subject: [PATCH 1/7] Fixes for Python 3 --- .gitignore | 3 ++ .travis.yml | 38 ++++--------------------- Makefile | 11 +++---- REQUIREMENTS | 3 -- pyvows/cli.py | 2 +- pyvows/reporting/common.py | 10 ++++--- pyvows/reporting/test.py | 5 +++- pyvows/reporting/xunit.py | 2 +- pyvows/runner/abc.py | 2 +- pyvows/runner/executionplan.py | 9 +++--- pyvows/runner/gevent.py | 30 ++++++++++--------- requirements-travis.txt | 4 --- requirements.txt | 6 ++++ setup.py | 10 +++---- tests/assertions/like_vows.py | 4 +-- tests/assertions/types/file_vows.py | 4 ++- tests/bugs/64_vows.py | 5 +++- tests/context_inheritance_vows.py | 8 ++++-- tests/prune_execution_vows.py | 2 +- tests/reporting/error_reporting_vows.py | 5 +++- tests/reporting/xunit_reporter_vows.py | 6 ++-- tests/skipping_vows.py | 10 +++++-- 22 files changed, 87 insertions(+), 92 deletions(-) delete mode 100644 REQUIREMENTS delete mode 100644 requirements-travis.txt create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index c957c93..92ffc25 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ pyvows.iml bin/ include/ lib/ + +/coverage.xml +/pyvows.xml diff --git a/.travis.yml b/.travis.yml index 0b33eff..cdf1033 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,38 +1,10 @@ +sudo: false +dist: trusty language: python python: - - "2.6" - - "2.7" - -install: - # update aptitude - - sudo apt-get update -y - - # install aptitude packages - - LDFLAGS=-lm sudo apt-get install -y $(< requirements-travis.txt) - - # install python requirements - - make setup - - pip install coveralls - - # weird travis-ci python paths - - export PYTHONPATH=$PYTHONPATH:/usr/lib/pymodules/python2.7/ - - export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages - - export PYTHONPATH=$PYTHONPATH:/usr/lib/pyshared/python2.7/ - - export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages/ - - # verify requirements were met - - INSTALLDIR=$(python -c "import os; import gevent; print(os.path.dirname(gevent.__file__))") - - + - 2.7 + - 3.6 script: - - export PYTHONPATH=$PYTHONPATH:/usr/lib/pymodules/python2.7/ - - export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages - - export PYTHONPATH=$PYTHONPATH:/usr/lib/pyshared/python2.7/ - - export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages/ - - # finally run tests - - env PYTHONPATH=. coverage run --source=pyvows ./pyvows/__main__.py - - + - make coverage after_success: - coveralls diff --git a/Makefile b/Makefile index 57082eb..5f42262 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,10 @@ -vows test: +test: @env PYTHONPATH=. python pyvows/cli.py --cover --cover-package=pyvows --cover-threshold=80.0 --profile tests/ -ci_test: setup - @env PYTHONPATH=. python pyvows/cli.py --cover --cover-package=pyvows --cover-threshold=80.0 --cover-report=pyvows.coverage.xml -x tests/ - -setup: - @pip install --upgrade --editable .\[tests\] +coverage: + @env PYTHONPATH=. python pyvows/cli.py --cover --cover-package=pyvows --cover-threshold=80.0 --cover-report=coverage.xml -x tests/ publish: python setup.py sdist upload -.PHONY: vows test setup publish ci_test +.PHONY: test coverage publish diff --git a/REQUIREMENTS b/REQUIREMENTS deleted file mode 100644 index 8f768c1..0000000 --- a/REQUIREMENTS +++ /dev/null @@ -1,3 +0,0 @@ -gevent -argparse -preggy diff --git a/pyvows/cli.py b/pyvows/cli.py index 4850340..45ca215 100755 --- a/pyvows/cli.py +++ b/pyvows/cli.py @@ -224,7 +224,7 @@ def main(): if xml: if arguments.cover_report: - with open(arguments.cover_report, 'w') as report: + with open(arguments.cover_report, 'wb') as report: report.write(xml) arguments.cover_threshold /= 100.0 diff --git a/pyvows/reporting/common.py b/pyvows/reporting/common.py index 94f4448..c6c1ed7 100644 --- a/pyvows/reporting/common.py +++ b/pyvows/reporting/common.py @@ -42,10 +42,10 @@ def ensure_encoded(thing, encoding='utf-8'): Currently used only for characters `✓` and `✗`. ''' - if isinstance(thing, unicode): - return thing.encode(encoding) - else: + if isinstance(thing, bytes) or not isinstance(thing, str): return thing + else: + return thing.encode(encoding) class VowsReporter(object): @@ -169,8 +169,10 @@ def print_traceback(self, err_type, err_obj, err_traceback, file=sys.stdout): '''Prints a color-formatted traceback with appropriate indentation.''' if isinstance(err_obj, AssertionError): error_msg = err_obj + elif isinstance(err_obj, bytes): + error_msg = err_obj.decode('utf8') else: - error_msg = unicode(err_obj) + error_msg = err_obj print(self.indent_msg(red(error_msg)), file=file) diff --git a/pyvows/reporting/test.py b/pyvows/reporting/test.py index 32e2642..6e63172 100644 --- a/pyvows/reporting/test.py +++ b/pyvows/reporting/test.py @@ -11,7 +11,10 @@ from __future__ import division, print_function import sys -from StringIO import StringIO +try: + from StringIO import StringIO +except: + from io import StringIO from pyvows.color import yellow, red, blue from pyvows.reporting.common import ( diff --git a/pyvows/reporting/xunit.py b/pyvows/reporting/xunit.py index f952dc3..969de3f 100644 --- a/pyvows/reporting/xunit.py +++ b/pyvows/reporting/xunit.py @@ -26,7 +26,7 @@ class XUnitReporter(object): def __init__(self, result): self.result_summary = self.summarize_results(result) - def write_report(self, filename, encoding='utf-8'): + def write_report(self, filename, encoding=None): # FIXME: Add Docstring with codecs.open(filename, 'w', encoding, 'replace') as output_file: output_file.write(self.to_xml(encoding)) diff --git a/pyvows/runner/abc.py b/pyvows/runner/abc.py index 3db72eb..6ded6fa 100644 --- a/pyvows/runner/abc.py +++ b/pyvows/runner/abc.py @@ -67,7 +67,7 @@ def run_vow(self, tests_collection, topic, ctx_obj, vow, vow_name, enumerated): vow_result['succeeded'] = True if self.on_vow_success: self.on_vow_success(vow_result) - except SkipTest, se: + except SkipTest as se: vow_result['skip'] = se except: err_type, err_value, err_traceback = sys.exc_info() diff --git a/pyvows/runner/executionplan.py b/pyvows/runner/executionplan.py index 3b344a0..65fc82a 100644 --- a/pyvows/runner/executionplan.py +++ b/pyvows/runner/executionplan.py @@ -15,7 +15,7 @@ def __init__(self, suites, exclusion_patterns, inclusion_patterns): def plan(self): plan = {} - for suiteName, contextClasses in self.suites.iteritems(): + for suiteName, contextClasses in self.suites.items(): plan[suiteName] = { 'contexts': {} } @@ -63,9 +63,10 @@ def plan_context(self, contextClass, idBase): ] context['vows'] = [ - name for name, vow in contextMembers if inspect.ismethod(vow) - and self.is_included(context['id'] + '.' + name) - and not self.is_excluded(name) + name for name, vow in contextMembers + if (inspect.ismethod(vow) or inspect.isfunction(vow)) + and self.is_included(context['id'] + '.' + name) + and not self.is_excluded(name) ] subcontexts = [ diff --git a/pyvows/runner/gevent.py b/pyvows/runner/gevent.py index 4314225..9fb869e 100644 --- a/pyvows/runner/gevent.py +++ b/pyvows/runner/gevent.py @@ -14,7 +14,10 @@ import inspect import sys import time -import StringIO +try: + from StringIO import StringIO +except: + from io import StringIO try: from colorama.ansitowin32 import AnsiToWin32 except ImportError: @@ -36,8 +39,8 @@ def AnsiToWin32(*args, **kwargs): class _LocalOutput(gevent.local.local): def __init__(self): - self.__dict__['stdout'] = StringIO.StringIO() - self.__dict__['stderr'] = StringIO.StringIO() + self.__dict__['stdout'] = StringIO() + self.__dict__['stderr'] = StringIO() class _StreamCapture(object): @@ -71,9 +74,9 @@ def run(self): start_time = time.time() result = VowsResult() if self.capture_output: - self._capture_streams(self.capture_output) + self._capture_streams(True) try: - for suiteName, suitePlan in self.execution_plan.iteritems(): + for suiteName, suitePlan in self.execution_plan.items(): batches = [batch for batch in self.suites[suiteName] if batch.__name__ in suitePlan['contexts']] for batch in batches: self.pool.spawn( @@ -88,7 +91,8 @@ def run(self): self.pool.join() finally: - self._capture_streams(False) + if self.capture_output: + self._capture_streams(False) result.elapsed_time = elapsed(start_time) return result @@ -125,11 +129,11 @@ def _run_setup_and_topic(ctx_obj, index): except Exception: raise VowsTopicError('setup', sys.exc_info()) - # Find & run topic function - if not hasattr(ctx_obj, 'topic'): # ctx_obj has no topic - return ctx_obj._get_first_available_topic(index) - try: + # Find & run topic function + if not hasattr(ctx_obj, 'topic'): # ctx_obj has no topic + return ctx_obj._get_first_available_topic(index) + topic_func = ctx_obj.topic topic_list = get_topics_for(topic_func, ctx_obj) @@ -239,11 +243,11 @@ def _update_execution_plan(): try: topic = _run_setup_and_topic(ctx_obj, index) _update_execution_plan() - except SkipTest, se: + except SkipTest as se: ctx_result['skip'] = se skipReason = se topic = None - except VowsTopicError, e: + except VowsTopicError as e: ctx_result['error'] = e skipReason = SkipTest('topic dependency failed') topic = None @@ -251,7 +255,7 @@ def _update_execution_plan(): if not ctx_result['error']: try: _run_teardown() - except Exception, e: + except Exception as e: ctx_result['error'] = e finally: ctx_result['stdout'] = VowsParallelRunner.output.stdout.getvalue() diff --git a/requirements-travis.txt b/requirements-travis.txt deleted file mode 100644 index cc2cc59..0000000 --- a/requirements-travis.txt +++ /dev/null @@ -1,4 +0,0 @@ -libevent-dev -libxml2-dev -libcurl4-gnutls-dev -python-pycurl-dbg diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..530eb98 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +gevent>=1.2.2 +preggy>=1.3.0 + +argparse>=1.4.0 +colorama>=0.3.7 +coverage>=4.1.1 diff --git a/setup.py b/setup.py index 1b4945e..af7e97e 100755 --- a/setup.py +++ b/setup.py @@ -18,14 +18,14 @@ _test_requires = [ - 'argparse', - 'colorama', - 'coverage' + 'argparse>=1.4.0', + 'colorama>=0.3.7', + 'coverage>=4.1.1' ] _install_requires = [ - 'gevent>=0.13.6', - 'preggy>=0.11.1', + 'gevent>=1.2.2', + 'preggy>=1.3.0', ] if sys.version_info < (2, 7): _install_requires.append('argparse >= 1.1') diff --git a/tests/assertions/like_vows.py b/tests/assertions/like_vows.py index 49b6d89..8fca8e9 100644 --- a/tests/assertions/like_vows.py +++ b/tests/assertions/like_vows.py @@ -8,6 +8,7 @@ # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Bernardo Heynemann heynemann@gmail.com +import sys from pyvows import Vows, expect @@ -47,9 +48,6 @@ def we_assert_it_is_like_42(self, topic): def we_assert_it_is_like_42_float(self, topic): expect(topic).to_be_like(42.0) - def we_assert_it_is_like_42_long(self, topic): - expect(topic).to_be_like(long(42)) - def we_assert_it_is_not_like_41(self, topic): expect(topic).Not.to_be_like(41) diff --git a/tests/assertions/types/file_vows.py b/tests/assertions/types/file_vows.py index 9249922..ae16022 100644 --- a/tests/assertions/types/file_vows.py +++ b/tests/assertions/types/file_vows.py @@ -15,7 +15,9 @@ STRINGS = { 'that_are_files': ( __file__, - unicode(__file__), + (__file__.decode('utf8') + if isinstance(__file__, bytes) \ + else __file__), ), 'that_are_not_files': ( diff --git a/tests/bugs/64_vows.py b/tests/bugs/64_vows.py index 248a089..451e3b4 100644 --- a/tests/bugs/64_vows.py +++ b/tests/bugs/64_vows.py @@ -11,7 +11,10 @@ from pyvows.result import VowsResult from pyvows.reporting import VowsTestReporter # , VowsDefaultReporter -from StringIO import StringIO +try: + from StringIO import StringIO +except: + from io import StringIO @Vows.batch diff --git a/tests/context_inheritance_vows.py b/tests/context_inheritance_vows.py index 741688d..dab1c32 100644 --- a/tests/context_inheritance_vows.py +++ b/tests/context_inheritance_vows.py @@ -31,7 +31,8 @@ def topic(self, ponies): # Second case: BaseSubcontext should be ignored. class BaseSubcontext(Vows.Context): - def topic(self, (Thingy, ponies)): + def topic(self, v): + (Thingy, ponies) = v self.ignore('prepare') for pony in ponies: yield (Thingy, self.prepare(pony)) @@ -56,7 +57,8 @@ class ActualContext(BaseContext): class ActualSubcontext(BaseContext.BaseSubcontext): def prepare(self, something): - return unicode(something) + return something.decode('utf8') if isinstance(something, bytes) else something - def pony_is_alicorn(self, (Thingy, pony)): + def pony_is_alicorn(self, v): + (Thingy, pony) = v expect(Thingy.alicorns).to_include(pony) diff --git a/tests/prune_execution_vows.py b/tests/prune_execution_vows.py index 9a708a4..e323f98 100644 --- a/tests/prune_execution_vows.py +++ b/tests/prune_execution_vows.py @@ -141,7 +141,7 @@ def the_excluded_context_is_not_included(self, topic): } expect(topic).to_equal(baseline) - class WithBothInclusionAndExclution(Vows.Context): + class WithBothInclusionAndExclusion(Vows.Context): @Vows.capture_error def topic(self): planner = ExecutionPlanner( diff --git a/tests/reporting/error_reporting_vows.py b/tests/reporting/error_reporting_vows.py index d290d2e..2846218 100644 --- a/tests/reporting/error_reporting_vows.py +++ b/tests/reporting/error_reporting_vows.py @@ -12,7 +12,10 @@ from pyvows.reporting import VowsDefaultReporter from pyvows.runner.abc import VowsTopicError -from StringIO import StringIO +try: + from StringIO import StringIO +except: + from io import StringIO # These tests check that the reporting, which happens after all tests # have run, correctly shows the errors raised in topic functions. diff --git a/tests/reporting/xunit_reporter_vows.py b/tests/reporting/xunit_reporter_vows.py index dec98f3..0433bc1 100644 --- a/tests/reporting/xunit_reporter_vows.py +++ b/tests/reporting/xunit_reporter_vows.py @@ -34,11 +34,11 @@ def topic(self): return reporter def should_create_xml_header(self, topic): - expect(topic.to_xml().find('')).to_equal(0) + expect(topic.to_xml().find(b'')).to_equal(0) def should_have_a_testsuite_node(self, topic): - expect(topic.to_xml()).to_match(r'.*') + expect(topic.to_xml()).to_match(br'.*') class WithDocument(Vows.Context): def topic(self, topic): diff --git a/tests/skipping_vows.py b/tests/skipping_vows.py index 03e8dab..c5e1534 100644 --- a/tests/skipping_vows.py +++ b/tests/skipping_vows.py @@ -6,7 +6,10 @@ from pyvows.reporting.xunit import XUnitReporter from pyvows.reporting.common import V_VERBOSE -from StringIO import StringIO +try: + from StringIO import StringIO +except: + from io import StringIO @Vows.batch @@ -331,7 +334,10 @@ def subcontext_shows_skipped_message(self, topic): def tests_should_not_run_vow_shows_run(self, topic): expect(topic).Not.to_include('? tests should not run\n') - expect(topic).to_include('tests should not run\n') + try: + expect(topic).to_include('tests should not run\n') + except: + expect(topic).to_include("b'tests should not run'\n") def subcontext_tests_should_also_not_run_vow_shows_skipped(self, topic): expect(topic).to_include('? subcontext tests should also not run\n') From b5119422b38c2b00c2aa6211eab9d159ba7db095 Mon Sep 17 00:00:00 2001 From: Marcelo Jorge Vieira Date: Mon, 25 Nov 2019 00:00:50 -0300 Subject: [PATCH 2/7] 3.8 + xenial --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cdf1033..b1508b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,11 @@ sudo: false -dist: trusty +dist: xenial language: python python: - 2.7 - 3.6 + - 3.8 script: - - make coverage + - make coverage after_success: - coveralls From 98e1b93a64305c7b829c49e5557f51da5a7d7525 Mon Sep 17 00:00:00 2001 From: Marcelo Jorge Vieira Date: Mon, 25 Nov 2019 00:07:32 -0300 Subject: [PATCH 3/7] Replaced 'async' with '_async' --- pyvows/runner/utils.py | 6 +++--- tests/async_vows.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyvows/runner/utils.py b/pyvows/runner/utils.py index 29ac7f4..00565ad 100644 --- a/pyvows/runner/utils.py +++ b/pyvows/runner/utils.py @@ -34,10 +34,10 @@ def get_topics_for(topic_function, ctx_obj): # check for decorated topic function if hasattr(topic_function, '_original'): # _wrapper_type is 'async_topic' or 'capture_error' - async = (getattr(topic_function, '_wrapper_type', None) == 'async_topic') + _async = (getattr(topic_function, '_wrapper_type', None) == 'async_topic') topic_function = topic_function._original else: - async = False + _async = False code = get_code_for(topic_function) @@ -48,7 +48,7 @@ def get_topics_for(topic_function, ctx_obj): expected_args = code.co_argcount - 1 # taking the callback argument into consideration - if async: + if _async: expected_args -= 1 # prepare to create `topics` list diff --git a/tests/async_vows.py b/tests/async_vows.py index 7c67b64..f25bc16 100644 --- a/tests/async_vows.py +++ b/tests/async_vows.py @@ -15,13 +15,13 @@ #------------------------------------------------------------------------------------------------- def asyncFunc(pool, callback): - def async(): + def _async(): time.sleep(0.1) return 10 def get_value(value): callback(value, 20, kwarg=30, kw2=40) - pool.apply_async(async, callback=get_value) + pool.apply_async(_async, callback=get_value) #------------------------------------------------------------------------------------------------- From f7ea3bf0a7f1215db73fcf8f6fdaa5e5864b544c Mon Sep 17 00:00:00 2001 From: Marcelo Jorge Vieira Date: Mon, 25 Nov 2019 00:45:53 -0300 Subject: [PATCH 4/7] XunitReporterVows --- tests/reporting/xunit_reporter_vows.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/reporting/xunit_reporter_vows.py b/tests/reporting/xunit_reporter_vows.py index 0433bc1..10986d7 100644 --- a/tests/reporting/xunit_reporter_vows.py +++ b/tests/reporting/xunit_reporter_vows.py @@ -37,8 +37,7 @@ def should_create_xml_header(self, topic): expect(topic.to_xml().find(b'')).to_equal(0) def should_have_a_testsuite_node(self, topic): - expect(topic.to_xml()).to_match(br'.*') + expect(topic.to_xml()).to_match(br'.*') class WithDocument(Vows.Context): def topic(self, topic): From a2f08a601b14becfb329cd94688c8689499b79f7 Mon Sep 17 00:00:00 2001 From: Marcelo Jorge Vieira Date: Mon, 25 Nov 2019 01:16:55 -0300 Subject: [PATCH 5/7] Makefile: added setup target (again) --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5f42262..f82d8f4 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,13 @@ -test: +vows test: @env PYTHONPATH=. python pyvows/cli.py --cover --cover-package=pyvows --cover-threshold=80.0 --profile tests/ +setup: + @pip install --upgrade --editable .\[tests\] + coverage: @env PYTHONPATH=. python pyvows/cli.py --cover --cover-package=pyvows --cover-threshold=80.0 --cover-report=coverage.xml -x tests/ publish: python setup.py sdist upload -.PHONY: test coverage publish +.PHONY: vows test setup coverage publish From 9665a4cd83c84ab90cc79670ea7072c5690a4965 Mon Sep 17 00:00:00 2001 From: Marcelo Jorge Vieira Date: Mon, 25 Nov 2019 22:52:06 -0300 Subject: [PATCH 6/7] preggy version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 530eb98..22da332 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ gevent>=1.2.2 -preggy>=1.3.0 +preggy>=1.4.4 argparse>=1.4.0 colorama>=0.3.7 From 89e21bc10f36575b011da036992c8a3a39d8b20d Mon Sep 17 00:00:00 2001 From: Marcelo Jorge Vieira Date: Mon, 25 Nov 2019 22:53:22 -0300 Subject: [PATCH 7/7] like_vows.py: unnecessary import --- tests/assertions/like_vows.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/assertions/like_vows.py b/tests/assertions/like_vows.py index 8fca8e9..2d1b8e2 100644 --- a/tests/assertions/like_vows.py +++ b/tests/assertions/like_vows.py @@ -8,7 +8,6 @@ # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Bernardo Heynemann heynemann@gmail.com -import sys from pyvows import Vows, expect