diff --git a/CHANGES.rst b/CHANGES.rst index 43b07266..97284b01 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,9 +1,11 @@ CHANGES ======= -0.5.1 (2017-04-xx) +0.5.1 (2017-05-xx) ------------------ +- Added support for "cargo test" + - Fixed unbound method type error #4 diff --git a/setup.py b/setup.py index 1fa62813..78011932 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup -version = '0.5.0' +version = '0.5.1' setup( @@ -37,5 +37,6 @@ clean_rust=setuptools_rust:clean_rust build_ext=setuptools_rust:build_ext build_rust=setuptools_rust:build_rust + test_rust=setuptools_rust:test_rust """ ) diff --git a/setuptools_rust/__init__.py b/setuptools_rust/__init__.py index 5127492a..de4daa17 100644 --- a/setuptools_rust/__init__.py +++ b/setuptools_rust/__init__.py @@ -5,10 +5,11 @@ from .build_ext import build_ext from .check import check_rust from .clean import clean_rust +from .test import test_rust from .extension import RustExtension __all__ = ('RustExtension', - 'check_rust', 'clean_rust', 'build_ext', 'build_rust') + 'check_rust', 'clean_rust', 'build_ext', 'build_rust', 'test_rust') patch.monkey_patch_dist(build_ext) diff --git a/setuptools_rust/test.py b/setuptools_rust/test.py new file mode 100644 index 00000000..d01e290a --- /dev/null +++ b/setuptools_rust/test.py @@ -0,0 +1,81 @@ +from __future__ import print_function, absolute_import +import os +import sys +import subprocess +from distutils.cmd import Command +from distutils.errors import ( + CompileError, DistutilsFileError, DistutilsExecError) + +import semantic_version + +from .extension import RustExtension +from .utils import cpython_feature, get_rust_version + +MIN_VERSION = semantic_version.Spec('>=1.15') + + +class test_rust(Command): + """ Run cargo test""" + + description = "test rust extensions" + + user_options = [] + + def initialize_options(self): + self.extensions = () + + def finalize_options(self): + self.extensions = [ext for ext in self.distribution.rust_extensions + if isinstance(ext, RustExtension)] + + def run(self): + if not self.extensions: + return + + version = get_rust_version() + if version not in MIN_VERSION: + print('Rust version mismatch: required rust%s got rust%s' % ( + MIN_VERSION, version)) + return + + # Make sure that if pythonXX-sys is used, it builds against the current + # executing python interpreter. + bindir = os.path.dirname(sys.executable) + + env = os.environ.copy() + env.update({ + # disables rust's pkg-config seeking for specified packages, + # which causes pythonXX-sys to fall back to detecting the + # interpreter from the path. + "PYTHON_2.7_NO_PKG_CONFIG": "1", + "PATH": bindir + os.pathsep + os.environ.get("PATH", "") + }) + + for ext in self.extensions: + if not os.path.exists(ext.path): + raise DistutilsFileError( + "Can not file rust extension project file: %s" % ext.path) + + features = set(ext.features) + features.update(cpython_feature(ext=False)) + + # build cargo command + args = (["cargo", "test", "--manifest-path", ext.path, + "--features", " ".join(features)] + + list(ext.args or [])) + + # Execute cargo command + print(' '.join(args)) + try: + subprocess.check_output(args) + except subprocess.CalledProcessError as e: + raise CompileError( + "cargo failed with code: %d\n%s" % ( + e.returncode, e.output.decode("utf-8"))) + except OSError: + raise DistutilsExecError( + "Unable to execute 'cargo' - this package " + "requires rust to be installed and " + "cargo to be on the PATH") + else: + print("Test has been completed for '%s' extension" % ext.name) diff --git a/setuptools_rust/utils.py b/setuptools_rust/utils.py index e81a7c8b..0ca908d4 100644 --- a/setuptools_rust/utils.py +++ b/setuptools_rust/utils.py @@ -6,12 +6,18 @@ import semantic_version -def cpython_feature(): +def cpython_feature(ext=True): version = sys.version_info if (2, 7) < version < (2, 8): - return ("cpython/python27-sys", "cpython/extension-module-2-7") + if ext: + return ("cpython/python27-sys", "cpython/extension-module-2-7") + else: + return ("cpython/python27-sys",) elif (3, 3) < version: - return ("cpython/python3-sys", "cpython/extension-module") + if ext: + return ("cpython/python3-sys", "cpython/extension-module") + else: + return ("cpython/python3-sys",) else: raise DistutilsPlatformError( "Unsupported python version: %s" % sys.version)