From 35446dc2fccaa8ea80b0738406e6ce87feb2c462 Mon Sep 17 00:00:00 2001 From: stonebig Date: Sat, 11 May 2019 14:11:32 +0200 Subject: [PATCH 01/23] adapt to Python3.8 with PEP570 .... please update also vendored joblib --- cloudpickle/cloudpickle.py | 55 +++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index d84cce76d..0da94df62 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -168,24 +168,43 @@ def inner(value): (), ) else: - return types.CodeType( - co.co_argcount, - co.co_kwonlyargcount, - co.co_nlocals, - co.co_stacksize, - co.co_flags, - co.co_code, - co.co_consts, - co.co_names, - co.co_varnames, - co.co_filename, - co.co_name, - co.co_firstlineno, - co.co_lnotab, - co.co_cellvars, # this is the trickery - (), - ) - + try: + return types.CodeType( + co.co_argcount, + co.co_kwonlyargcount, + co.co_nlocals, + co.co_stacksize, + co.co_flags, + co.co_code, + co.co_consts, + co.co_names, + co.co_varnames, + co.co_filename, + co.co_name, + co.co_firstlineno, + co.co_lnotab, + co.co_cellvars, # this is the trickery + (), + ) + except: + return types.CodeType( + co.co_argcount, + co.co_posonlyargcount, # Python3.8 with PEP570 + co.co_kwonlyargcount, + co.co_nlocals, + co.co_stacksize, + co.co_flags, + co.co_code, + co.co_consts, + co.co_names, + co.co_varnames, + co.co_filename, + co.co_name, + co.co_firstlineno, + co.co_lnotab, + co.co_cellvars, # this is the trickery + (), + ) _cell_set_template_code = _make_cell_set_template_code() From 273e723cb6bdc945a2612a42157be7ef678f39c9 Mon Sep 17 00:00:00 2001 From: stonebig Date: Sat, 11 May 2019 14:26:17 +0200 Subject: [PATCH 02/23] update cloudpickle --- cloudpickle/cloudpickle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 0da94df62..76b0f0c30 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -186,7 +186,7 @@ def inner(value): co.co_cellvars, # this is the trickery (), ) - except: + except: return types.CodeType( co.co_argcount, co.co_posonlyargcount, # Python3.8 with PEP570 From 04e29092f5e5e7654b4824afc3b927dc788bf212 Mon Sep 17 00:00:00 2001 From: stonebig Date: Sat, 11 May 2019 16:20:42 +0200 Subject: [PATCH 03/23] implement same test as for ipython --- cloudpickle/cloudpickle.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 76b0f0c30..0d04a4903 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -168,9 +168,10 @@ def inner(value): (), ) else: - try: + if sys.version_info > (3, 8, 0, 'alpha', 3): return types.CodeType( co.co_argcount, + co.co_posonlyargcount, # Python3.8 with PEP570 co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, @@ -186,10 +187,9 @@ def inner(value): co.co_cellvars, # this is the trickery (), ) - except: + else: return types.CodeType( co.co_argcount, - co.co_posonlyargcount, # Python3.8 with PEP570 co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, From 67e3ad206f16494ab892e05c4ec77bec495ff70d Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Mon, 13 May 2019 20:08:45 +0200 Subject: [PATCH 04/23] MNT code reducer now includes pos-only args --- cloudpickle/cloudpickle.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 0d04a4903..59a42d076 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -390,12 +390,23 @@ def save_codeobject(self, obj): Save a code object """ if PY3: # pragma: no branch - args = ( - obj.co_argcount, obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, - obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, obj.co_varnames, - obj.co_filename, obj.co_name, obj.co_firstlineno, obj.co_lnotab, obj.co_freevars, - obj.co_cellvars - ) + if hasattr(obj, "co_posonlyargcount"): + args = ( + obj.co_argcount, obj.co_posonlyargcount, + obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, + obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, + obj.co_varnames, obj.co_filename, obj.co_name, + obj.co_firstlineno, obj.co_lnotab, obj.co_freevars, + obj.co_cellvars + ) + else: + args = ( + obj.co_argcount, obj.co_kwonlyargcount, obj.co_nlocals, + obj.co_stacksize, obj.co_flags, obj.co_code, obj.co_consts, + obj.co_names, obj.co_varnames, obj.co_filename, + obj.co_name, obj.co_firstlineno, obj.co_lnotab, + obj.co_freevars, obj.co_cellvars + ) else: args = ( obj.co_argcount, obj.co_nlocals, obj.co_stacksize, obj.co_flags, obj.co_code, From 2320516e4444aedc3bce737633182c2c656783e2 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Mon, 13 May 2019 20:18:26 +0200 Subject: [PATCH 05/23] TST test function with posonlyargument pickling --- tests/cloudpickle_test.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index 8f358ac64..56d22e3bb 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -1639,6 +1639,31 @@ def f(a, *, b=1): """.format(protocol=self.protocol) assert_run_python_script(textwrap.dedent(code)) + @pytest.mark.skipif(hasattr(types.CodeType, "co_posonlyargcount"), + reason="Not all python version support this syntax") + def test_interactively_defined_func_with_positional_only_argument(self): + # Fixes https://github.com/cloudpipe/cloudpickle/issues/266 + # The source code of this test is bundled in a string and is ran from + # the __main__ module of a subprocess in order to avoid a SyntaxError + # in versions of python that do not support positional-only argument + # syntax. + code = """ + from cloudpickle import loads, dumps + + def f(a, /, b=1): + return a + b + + depickled_f = loads(dumps(f, protocol={protocol})) + + for func in (f, depickled_f): + assert func(2) == 3 + assert func.__code__.co_posonlyargcount == 1 + with pytest.raises(TypeError): + func(a=2) + + """.format(protocol=self.protocol) + assert_run_python_script(textwrap.dedent(code)) + class Protocol2CloudPickleTest(CloudPickleTest): protocol = 2 From c9bec0617dee8f4bca4bf1fa59064a43c0574c74 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Mon, 13 May 2019 20:20:07 +0200 Subject: [PATCH 06/23] MNT use an attribute-based condition --- cloudpickle/cloudpickle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 59a42d076..22be7a2b4 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -168,7 +168,7 @@ def inner(value): (), ) else: - if sys.version_info > (3, 8, 0, 'alpha', 3): + if hasattr(types.CodeType, "co_posonlyargcount"): return types.CodeType( co.co_argcount, co.co_posonlyargcount, # Python3.8 with PEP570 From f67f63ad7f25dd2f786dd255dc1fd197fede53fb Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Mon, 13 May 2019 20:22:59 +0200 Subject: [PATCH 07/23] MNT update changelog --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index e21ae720d..ee0101c67 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ 1.1.0 ===== +- Support the pickling of interactively-defined functions with positional-only + arguments. ([issue #266](https://github.com/cloudpipe/cloudpickle/pull/266)) + - Track the provenance of dynamic classes and enums so as to preseve the usual `isinstance` relationship between pickled objects and their original class defintions. From 30c84eecdf0426a4526f5b0506d26bda209d260f Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 14:32:49 +0200 Subject: [PATCH 08/23] fixup! TST test function with posonlyargument pickling --- tests/cloudpickle_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index 56d22e3bb..b1ca03d8a 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -1639,7 +1639,7 @@ def f(a, *, b=1): """.format(protocol=self.protocol) assert_run_python_script(textwrap.dedent(code)) - @pytest.mark.skipif(hasattr(types.CodeType, "co_posonlyargcount"), + @pytest.mark.skipif(not hasattr(types.CodeType, "co_posonlyargcount"), reason="Not all python version support this syntax") def test_interactively_defined_func_with_positional_only_argument(self): # Fixes https://github.com/cloudpipe/cloudpickle/issues/266 @@ -1648,6 +1648,7 @@ def test_interactively_defined_func_with_positional_only_argument(self): # in versions of python that do not support positional-only argument # syntax. code = """ + import pytest from cloudpickle import loads, dumps def f(a, /, b=1): From 2133808fdcd7c8f6283e0e39aa015811661fa1a2 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 14:37:08 +0200 Subject: [PATCH 09/23] CI add python3.8 to travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 300244df6..480796438 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,8 @@ matrix: - os: linux dist: trusty python: "pypy3" + - os: linux + python: "3.8-dev" - os: linux python: 3.7 - os: linux From 73491973e3e613617ad736461935d150ac290f2d Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 14:38:35 +0200 Subject: [PATCH 10/23] fixup! TST test function with posonlyargument pickling --- tests/cloudpickle_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index b1ca03d8a..e833e0663 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -1640,7 +1640,7 @@ def f(a, *, b=1): assert_run_python_script(textwrap.dedent(code)) @pytest.mark.skipif(not hasattr(types.CodeType, "co_posonlyargcount"), - reason="Not all python version support this syntax") + reason="Not all python versions support this syntax") def test_interactively_defined_func_with_positional_only_argument(self): # Fixes https://github.com/cloudpipe/cloudpickle/issues/266 # The source code of this test is bundled in a string and is ran from From d01cdf44462e4ea49a3bacc46109ce58f5d98334 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 14:48:38 +0200 Subject: [PATCH 11/23] CI skip scipy tests on 3.8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 480796438..14728ff2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,7 @@ install: - pip install . - pip install --upgrade -r dev-requirements.txt - pip install tornado - - if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then + - if ! [[ $TRAVIS_PYTHON_VERSION =~ (pypy*|3.8)) ]]; then pip install numpy scipy; fi - if [[ $PROJECT != "" ]]; then From 7c5933e18911a537b8edcc09ba334ee9037e33ca Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 14:52:20 +0200 Subject: [PATCH 12/23] fixup! CI skip scipy tests on 3.8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 14728ff2e..6de282fcc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,7 @@ install: - pip install . - pip install --upgrade -r dev-requirements.txt - pip install tornado - - if ! [[ $TRAVIS_PYTHON_VERSION =~ (pypy*|3.8)) ]]; then + - if ! [[ $TRAVIS_PYTHON_VERSION =~ (pypy*|3.8) ]]; then pip install numpy scipy; fi - if [[ $PROJECT != "" ]]; then From 9c6cb35431ec2719b1367ba796d877979fdd96f4 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 14:56:45 +0200 Subject: [PATCH 13/23] CI use python nightly build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6de282fcc..b845b71ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ matrix: dist: trusty python: "pypy3" - os: linux - python: "3.8-dev" + python: "nightly" - os: linux python: 3.7 - os: linux From a219dde251cff3448a67a4f84bdf8facc34d1d58 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 15:03:08 +0200 Subject: [PATCH 14/23] fixup! CI use python nightly build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b845b71ed..f86b98a7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,7 @@ install: - pip install . - pip install --upgrade -r dev-requirements.txt - pip install tornado - - if ! [[ $TRAVIS_PYTHON_VERSION =~ (pypy*|3.8) ]]; then + - if ! [[ $TRAVIS_PYTHON_VERSION =~ (pypy|3.8|nightly).* ]]; then pip install numpy scipy; fi - if [[ $PROJECT != "" ]]; then From 8a0974f0136e529b4dd606dad853c57757c4b748 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 15:06:36 +0200 Subject: [PATCH 15/23] fixup! TST test function with posonlyargument pickling --- tests/cloudpickle_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index e833e0663..4fb1e2e4e 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -1640,7 +1640,7 @@ def f(a, *, b=1): assert_run_python_script(textwrap.dedent(code)) @pytest.mark.skipif(not hasattr(types.CodeType, "co_posonlyargcount"), - reason="Not all python versions support this syntax") + reason="Requires positional-only argument syntax") def test_interactively_defined_func_with_positional_only_argument(self): # Fixes https://github.com/cloudpipe/cloudpickle/issues/266 # The source code of this test is bundled in a string and is ran from From 1e555e3fd13962d7dd08d6339f6f735542b2ed07 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 15:13:22 +0200 Subject: [PATCH 16/23] CI increase coverage stats --- cloudpickle/cloudpickle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 22be7a2b4..1d774b8ce 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -390,7 +390,7 @@ def save_codeobject(self, obj): Save a code object """ if PY3: # pragma: no branch - if hasattr(obj, "co_posonlyargcount"): + if hasattr(obj, "co_posonlyargcount"): # pragma: no branch args = ( obj.co_argcount, obj.co_posonlyargcount, obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, From a1330f6a01cfd154fe2b36450c28f6fa61271f31 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 15:20:16 +0200 Subject: [PATCH 17/23] fixup! CI increase coverage stats --- cloudpickle/cloudpickle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 1d774b8ce..fcdac7510 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -168,7 +168,7 @@ def inner(value): (), ) else: - if hasattr(types.CodeType, "co_posonlyargcount"): + if hasattr(types.CodeType, "co_posonlyargcount"): # pragma: no branch return types.CodeType( co.co_argcount, co.co_posonlyargcount, # Python3.8 with PEP570 From e34e4f6141e4ebf6da8a56fda84f17e02b07f8ad Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 15:54:16 +0200 Subject: [PATCH 18/23] CI build python from source for new python versions --- .travis.yml | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index f86b98a7f..158fa37ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,8 @@ matrix: dist: trusty python: "pypy3" - os: linux - python: "nightly" + if: commit_message =~ /(\[ci python-nightly\])/ + env: PYTHON_NIGHTLY=1 - os: linux python: 3.7 - os: linux @@ -71,15 +72,30 @@ before_install: export PATH="$PYTHON_ROOT:$PYTHON_ROOT/Scripts:$PATH"; python -m pip install --upgrade pip; fi + - if [[ "$BUILD_PY_FROM_SOURCE" == 1 ]]; then + export VENV_DIR="$HOME/python38"; + pushd ..; + git clone https://github.com/python/cpython.git; + pushd cpython; + ./configure; + make; + ./python -m venv "$VENV_DIR"; + popd; + popd; + export PYTHON_EXE="$VENV_DIR/bin/python"; + else + export PYTHON_EXE="python"; + fi + install: - - pip install . - - pip install --upgrade -r dev-requirements.txt - - pip install tornado - - if ! [[ $TRAVIS_PYTHON_VERSION =~ (pypy|3.8|nightly).* ]]; then - pip install numpy scipy; + - $PYTHON_EXE -m pip install . + - $PYTHON_EXE -m pip install --upgrade -r dev-requirements.txt + - $PYTHON_EXE -m pip install tornado + - if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* && "$PYTHON_NIGHTLY" != 1 ]]; then + $PYTHON_EXE -m pip install numpy scipy; fi - if [[ $PROJECT != "" ]]; then - pip install $TEST_REQUIREMENTS; + $PYTHON_EXE -m pip install $TEST_REQUIREMENTS; pushd ..; git clone $PROJECT_URL; if [[ $PROJECT == "joblib" ]]; then @@ -87,16 +103,16 @@ install: source vendor_cloudpickle.sh ../../../cloudpickle; popd; fi; - pip install ./$PROJECT; + $PYTHON_EXE -m pip install ./$PROJECT; popd; fi - - pip list + - $PYTHON_EXE -m pip list before_script: # stop the build if there are Python syntax errors or undefined names - - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics + - $PYTHON_EXE -m flake8 . --count --verbose --select=E901,E999,F821,F822,F823 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - python ci/install_coverage_subprocess_pth.py + - $PYTHON_EXE -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - $PYTHON_EXE ci/install_coverage_subprocess_pth.py script: - COVERAGE_PROCESS_START="$TRAVIS_BUILD_DIR/.coveragerc" PYTHONPATH='.:tests' pytest -r s - | From cff2e3a31fa5faecb6ad5ab63322ef8c72f95806 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 16:00:14 +0200 Subject: [PATCH 19/23] [ci python-nightly] From dd75b203fb52567d68f23b168b4fbb56cf83e980 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 16:02:44 +0200 Subject: [PATCH 20/23] stale variable --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 158fa37ee..e07da32d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,7 @@ before_install: export PATH="$PYTHON_ROOT:$PYTHON_ROOT/Scripts:$PATH"; python -m pip install --upgrade pip; fi - - if [[ "$BUILD_PY_FROM_SOURCE" == 1 ]]; then + - if [[ "$PYTHON_NIGHTLY" == 1 ]]; then export VENV_DIR="$HOME/python38"; pushd ..; git clone https://github.com/python/cpython.git; From f70da0077b34077475afc42a78fbc07ec16a11f7 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 16:02:57 +0200 Subject: [PATCH 21/23] [ci python-nightly] From 5718fdfbb59bcade322de4b728aa3a06461ffa04 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 16:17:20 +0200 Subject: [PATCH 22/23] fixup! CI build python from source for new python versions --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e07da32d4..7661144e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -114,11 +114,11 @@ before_script: - $PYTHON_EXE -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - $PYTHON_EXE ci/install_coverage_subprocess_pth.py script: - - COVERAGE_PROCESS_START="$TRAVIS_BUILD_DIR/.coveragerc" PYTHONPATH='.:tests' pytest -r s + - COVERAGE_PROCESS_START="$TRAVIS_BUILD_DIR/.coveragerc" PYTHONPATH='.:tests' $PYTHON_EXE -m pytest -r s - | if [[ $PROJECT != "" ]]; then pushd ../$PROJECT - pytest -vl + $PYTHON_EXE -m pytest -vl TEST_RETURN_CODE=$? popd if [[ "$TEST_RETURN_CODE" != "0" ]]; then From c2e2cbec7a1e269e1b2d865c8303027f4002e53c Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 14 May 2019 16:18:32 +0200 Subject: [PATCH 23/23] [ci python-nightly]