diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index b16a2ae1..00000000 --- a/.coveragerc +++ /dev/null @@ -1,32 +0,0 @@ -[run] - -source = extension_helpers - -omit = - extension_helpers/*/setup_package.py - extension_helpers/tests/* - extension_helpers/conftest.py - -[report] - -omit = - extension_helpers/*/setup_package.py - extension_helpers/tests/* - extension_helpers/conftest.py - -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about packages we have installed - except ImportError - - # Don't complain if tests don't hit assertions - raise AssertionError - raise NotImplementedError - - # Don't complain about script hooks - def main\(.*\): - - # Ignore branches that don't pertain to this version of Python - pragma: py{ignore_python_version} diff --git a/CHANGES.rst b/CHANGES.rst index 2608991d..344313db 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,8 @@ * Removed any direct usage of distutils. [#34] +* Remove support for the undocumented --compiler argument to setup.py. [#36] + 0.1 (2019-12-18) ---------------- diff --git a/extension_helpers/__init__.py b/extension_helpers/__init__.py index 77362205..5ccfe0c5 100644 --- a/extension_helpers/__init__.py +++ b/extension_helpers/__init__.py @@ -1,5 +1,4 @@ -from ._distutils_helpers import get_compiler from ._openmp_helpers import add_openmp_flags_if_available -from ._setup_helpers import get_extensions, pkg_config +from ._setup_helpers import get_compiler, get_extensions, pkg_config from ._utils import import_file, write_if_different from .version import version as __version__ diff --git a/extension_helpers/_distutils_helpers.py b/extension_helpers/_distutils_helpers.py deleted file mode 100644 index 859932de..00000000 --- a/extension_helpers/_distutils_helpers.py +++ /dev/null @@ -1,109 +0,0 @@ -""" -This module contains various utilities for introspecting the distutils -module and the setup process. - -Some of these utilities require the -`extension_helpers.setup_helpers.register_commands` function to be called first, -as it will affect introspection of setuptools command-line arguments. Other -utilities in this module do not have that restriction. -""" - -import os -import sys - -from setuptools.command.build_ext import new_compiler -from setuptools.dist import Distribution -from setuptools.errors import DistutilsError - -from ._utils import silence - -__all__ = ['get_compiler'] - - -def get_dummy_distribution(): - """ - Returns a distutils Distribution object used to instrument the setup - environment before calling the actual setup() function. - """ - - # Pre-parse the Distutils command-line options and config files to if - # the option is set. - dist = Distribution({'script_name': os.path.basename(sys.argv[0]), - 'script_args': sys.argv[1:]}) - - with silence(): - try: - dist.parse_config_files() - dist.parse_command_line() - except (DistutilsError, AttributeError, SystemExit): - # Let distutils handle DistutilsErrors itself AttributeErrors can - # get raise for ./setup.py --help SystemExit can be raised if a - # display option was used, for example - pass - - return dist - - -def get_distutils_option(option, commands): - """ Returns the value of the given distutils option. - - Parameters - ---------- - option : str - The name of the option - - commands : list of str - The list of commands on which this option is available - - Returns - ------- - val : str or None - the value of the given distutils option. If the option is not set, - returns None. - """ - - dist = get_dummy_distribution() - - for cmd in commands: - cmd_opts = dist.command_options.get(cmd) - if cmd_opts is not None and option in cmd_opts: - return cmd_opts[option][1] - else: - return None - - -def get_distutils_build_option(option): - """ Returns the value of the given distutils build option. - - Parameters - ---------- - option : str - The name of the option - - Returns - ------- - val : str or None - The value of the given distutils build option. If the option - is not set, returns None. - """ - return get_distutils_option(option, ['build', 'build_ext', 'build_clib']) - - -def get_compiler(): - """ - Determines the compiler that will be used to build extension modules. - - Returns - ------- - compiler : str - The compiler option specified for the build, build_ext, or build_clib - command; or the default compiler for the platform if none was - specified. - - """ - - compiler = get_distutils_build_option('compiler') - if compiler is None: - return new_compiler().compiler_type - - return compiler diff --git a/extension_helpers/_openmp_helpers.py b/extension_helpers/_openmp_helpers.py index d01d87c4..e7376d6f 100644 --- a/extension_helpers/_openmp_helpers.py +++ b/extension_helpers/_openmp_helpers.py @@ -22,7 +22,7 @@ from setuptools.command.build_ext import customize_compiler, get_config_var, new_compiler -from ._distutils_helpers import get_compiler +from ._setup_helpers import get_compiler __all__ = ['add_openmp_flags_if_available'] diff --git a/extension_helpers/_setup_helpers.py b/extension_helpers/_setup_helpers.py index f2f831cc..7e766da1 100644 --- a/extension_helpers/_setup_helpers.py +++ b/extension_helpers/_setup_helpers.py @@ -12,15 +12,30 @@ from collections import defaultdict from setuptools import Extension, find_packages +from setuptools.command.build_ext import new_compiler -from ._distutils_helpers import get_compiler from ._utils import import_file, walk_skip_hidden -__all__ = ['get_extensions', 'pkg_config'] +__all__ = ['get_compiler', 'get_extensions', 'pkg_config'] log = logging.getLogger(__name__) +def get_compiler(): + """ + Determines the compiler that will be used to build extension modules. + + Returns + ------- + compiler : str + The compiler option specified for the build, build_ext, or build_clib + command; or the default compiler for the platform if none was + specified. + + """ + return new_compiler().compiler_type + + def get_extensions(srcdir='.'): """ Collect all extensions from Cython files and ``setup_package.py`` files. diff --git a/extension_helpers/_utils.py b/extension_helpers/_utils.py index c32a11b7..198fde1b 100644 --- a/extension_helpers/_utils.py +++ b/extension_helpers/_utils.py @@ -9,41 +9,6 @@ __all__ = ['write_if_different', 'import_file'] -class _DummyFile(object): - """A noop writeable object.""" - - errors = '' - - def write(self, s): - pass - - def flush(self): - pass - - -@contextlib.contextmanager -def silence(): - """A context manager that silences sys.stdout and sys.stderr.""" - - old_stdout = sys.stdout - old_stderr = sys.stderr - sys.stdout = _DummyFile() - sys.stderr = _DummyFile() - exception_occurred = False - try: - yield - except: # noqa - exception_occurred = True - # Go ahead and clean up so that exception handling can work normally - sys.stdout = old_stdout - sys.stderr = old_stderr - raise - - if not exception_occurred: - sys.stdout = old_stdout - sys.stderr = old_stderr - - if sys.platform == 'win32': import ctypes @@ -162,7 +127,7 @@ def import_file(filename, name=None): if name is None: basename = os.path.splitext(filename)[0] - name = '_'.join(os.path.relpath(basename).split(os.sep)[1:]) + name = '_'.join(os.path.abspath(basename).split(os.sep)[1:]) if not os.path.exists(filename): raise ImportError('Could not import file {0}'.format(filename)) diff --git a/extension_helpers/tests/test_distutils_helpers.py b/extension_helpers/tests/test_distutils_helpers.py deleted file mode 100644 index af8a7328..00000000 --- a/extension_helpers/tests/test_distutils_helpers.py +++ /dev/null @@ -1,7 +0,0 @@ -from .._distutils_helpers import get_compiler - -POSSIBLE_COMPILERS = ['unix', 'msvc', 'bcpp', 'cygwin', 'mingw32'] - - -def test_get_compiler(): - assert get_compiler() in POSSIBLE_COMPILERS diff --git a/extension_helpers/tests/test_setup_helpers.py b/extension_helpers/tests/test_setup_helpers.py index abbf8dc4..9dc572d9 100644 --- a/extension_helpers/tests/test_setup_helpers.py +++ b/extension_helpers/tests/test_setup_helpers.py @@ -5,7 +5,7 @@ import pytest -from .._setup_helpers import get_extensions +from .._setup_helpers import get_compiler, get_extensions from . import cleanup_import, run_setup extension_helpers_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) # noqa @@ -19,6 +19,13 @@ def teardown_module(module): os.remove(tmpfile) +POSSIBLE_COMPILERS = ['unix', 'msvc', 'bcpp', 'cygwin', 'mingw32'] + + +def test_get_compiler(): + assert get_compiler() in POSSIBLE_COMPILERS + + def _extension_test_package(tmpdir, request, extension_type='c', include_numpy=False): """Creates a simple test package with an extension module.""" diff --git a/extension_helpers/tests/test_utils.py b/extension_helpers/tests/test_utils.py new file mode 100644 index 00000000..dc014886 --- /dev/null +++ b/extension_helpers/tests/test_utils.py @@ -0,0 +1,26 @@ +import os +import time + +from .._utils import import_file, write_if_different + + +def test_import_file(tmpdir): + filename = str(tmpdir / 'spam.py') + with open(filename, 'w') as f: + f.write('magic = 12345') + module = import_file(filename) + assert module.magic == 12345 + + +def test_write_if_different(tmpdir): + filename = str(tmpdir / 'test.txt') + write_if_different(filename, b'abc') + time1 = os.path.getmtime(filename) + time.sleep(0.01) + write_if_different(filename, b'abc') + time2 = os.path.getmtime(filename) + assert time2 == time1 + time.sleep(0.01) + write_if_different(filename, b'abcd') + time3 = os.path.getmtime(filename) + assert time3 > time1 diff --git a/setup.cfg b/setup.cfg index 31355d84..30b41f5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -56,3 +56,28 @@ balanced_wrapping = True include_trailing_comma = false length_sort = False length_sort_sections=stdlib + +[coverage:run] +omit = + extension_helpers/*/setup_package.py + extension_helpers/tests/* + extension_helpers/conftest.py + */extension_helpers/*/setup_package.py + */extension_helpers/tests/* + */extension_helpers/conftest.py + +[coverage:report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + # Don't complain about packages we have installed + except ImportError + # Don't complain if tests don't hit assertions + raise AssertionError + raise NotImplementedError + # Don't complain about script hooks + def main\(.*\): + # Ignore branches that don't pertain to this version of Python + pragma: py{ignore_python_version} + # Don't complain about IPython completion helper + def _ipython_key_completions_ diff --git a/tox.ini b/tox.ini index 28355849..eabe4e70 100644 --- a/tox.ini +++ b/tox.ini @@ -40,7 +40,7 @@ commands = dev: pip install setuptools_repo/ --no-build-isolation pip freeze test: python -c 'import setuptools; print(setuptools.__version__)' - test: pytest --pyargs extension_helpers {toxinidir}/docs --cov extension_helpers {posargs} + test: pytest --pyargs extension_helpers {toxinidir}/docs --cov extension_helpers --cov-config={toxinidir}/setup.cfg {posargs} build_docs: sphinx-build -W -b html . _build/html [testenv:py39-downstream]