From 59ac457a637e8a05df70d88b875023525cd92331 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 20:58:07 -0500 Subject: [PATCH 1/9] Move the source code to an `src` folder This more clearly indicates the files that will eventually become importable. --- .bumpversion.cfg | 2 +- pyproject.toml | 2 +- {pep517 => src/pep517}/__init__.py | 0 {pep517 => src/pep517}/_compat.py | 0 {pep517 => src/pep517}/build.py | 0 {pep517 => src/pep517}/check.py | 0 {pep517 => src/pep517}/colorlog.py | 0 {pep517 => src/pep517}/dirtools.py | 0 {pep517 => src/pep517}/envbuild.py | 0 {pep517 => src/pep517}/in_process/__init__.py | 0 {pep517 => src/pep517}/in_process/_in_process.py | 0 {pep517 => src/pep517}/meta.py | 0 {pep517 => src/pep517}/wrappers.py | 0 tox.ini | 4 ++-- 14 files changed, 4 insertions(+), 4 deletions(-) rename {pep517 => src/pep517}/__init__.py (100%) rename {pep517 => src/pep517}/_compat.py (100%) rename {pep517 => src/pep517}/build.py (100%) rename {pep517 => src/pep517}/check.py (100%) rename {pep517 => src/pep517}/colorlog.py (100%) rename {pep517 => src/pep517}/dirtools.py (100%) rename {pep517 => src/pep517}/envbuild.py (100%) rename {pep517 => src/pep517}/in_process/__init__.py (100%) rename {pep517 => src/pep517}/in_process/_in_process.py (100%) rename {pep517 => src/pep517}/meta.py (100%) rename {pep517 => src/pep517}/wrappers.py (100%) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 7eb57d2..cb59586 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -3,4 +3,4 @@ current_version = 0.13.0 commit = True tag = True -[bumpversion:file:pep517/__init__.py] +[bumpversion:file:src/pep517/__init__.py] diff --git a/pyproject.toml b/pyproject.toml index f24e689..132893d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["flit_core >=2,<4"] +requires = ["flit_core >=3.2,<4"] build-backend = "flit_core.buildapi" [tool.flit.metadata] diff --git a/pep517/__init__.py b/src/pep517/__init__.py similarity index 100% rename from pep517/__init__.py rename to src/pep517/__init__.py diff --git a/pep517/_compat.py b/src/pep517/_compat.py similarity index 100% rename from pep517/_compat.py rename to src/pep517/_compat.py diff --git a/pep517/build.py b/src/pep517/build.py similarity index 100% rename from pep517/build.py rename to src/pep517/build.py diff --git a/pep517/check.py b/src/pep517/check.py similarity index 100% rename from pep517/check.py rename to src/pep517/check.py diff --git a/pep517/colorlog.py b/src/pep517/colorlog.py similarity index 100% rename from pep517/colorlog.py rename to src/pep517/colorlog.py diff --git a/pep517/dirtools.py b/src/pep517/dirtools.py similarity index 100% rename from pep517/dirtools.py rename to src/pep517/dirtools.py diff --git a/pep517/envbuild.py b/src/pep517/envbuild.py similarity index 100% rename from pep517/envbuild.py rename to src/pep517/envbuild.py diff --git a/pep517/in_process/__init__.py b/src/pep517/in_process/__init__.py similarity index 100% rename from pep517/in_process/__init__.py rename to src/pep517/in_process/__init__.py diff --git a/pep517/in_process/_in_process.py b/src/pep517/in_process/_in_process.py similarity index 100% rename from pep517/in_process/_in_process.py rename to src/pep517/in_process/_in_process.py diff --git a/pep517/meta.py b/src/pep517/meta.py similarity index 100% rename from pep517/meta.py rename to src/pep517/meta.py diff --git a/pep517/wrappers.py b/src/pep517/wrappers.py similarity index 100% rename from pep517/wrappers.py rename to src/pep517/wrappers.py diff --git a/tox.ini b/tox.ini index 00b1010..354982b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = py36, py37, py38, py39, py310, py311, pypy3, isort -skipsdist = true +isolated_build = true [testenv] passenv = @@ -14,7 +14,7 @@ commands = python -m isort --check --diff {toxinidir} [testenv:flake8] deps = flake8 -commands = flake8 pep517 +commands = flake8 src [testenv:release] skip_install = True From 1dada01e13060a7b308942def7ca8765857b2417 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 21:01:06 -0500 Subject: [PATCH 2/9] Drop the deprecated functionality This functionality does not need to be maintained after this project is renamed. --- README.rst | 40 -------- src/pep517/build.py | 126 ------------------------- src/pep517/check.py | 207 ----------------------------------------- src/pep517/colorlog.py | 113 ---------------------- src/pep517/dirtools.py | 19 ---- src/pep517/envbuild.py | 170 --------------------------------- src/pep517/meta.py | 93 ------------------ tests/test_build.py | 27 ------ tests/test_envbuild.py | 39 -------- tests/test_meta.py | 26 ------ 10 files changed, 860 deletions(-) delete mode 100644 src/pep517/build.py delete mode 100644 src/pep517/check.py delete mode 100644 src/pep517/colorlog.py delete mode 100644 src/pep517/dirtools.py delete mode 100644 src/pep517/envbuild.py delete mode 100644 src/pep517/meta.py delete mode 100644 tests/test_build.py delete mode 100644 tests/test_envbuild.py delete mode 100644 tests/test_meta.py diff --git a/README.rst b/README.rst index a035f33..77f6c5f 100644 --- a/README.rst +++ b/README.rst @@ -47,43 +47,3 @@ Usage—you are responsible for ensuring build requirements are available: destination = 'also/a/folder' whl_filename = hooks.build_wheel(destination, config_options) assert os.path.isfile(os.path.join(destination, whl_filename)) - -Deprecated high-level ---------------------- - -For now, ``pep517`` also contains higher-level functions which install the build -dependencies into a temporary environment and build a wheel/sdist using them. -This is a rough implementation, e.g. it does not do proper build isolation. -The `PyPA build project `_ is recommended as an -alternative, although it's still quite young in October 2020. -This layer of functionality in ``pep517`` is now deprecated, but won't be -removed for some time, as there is code relying on it. - -High level usage, with build requirements handled: - -.. code-block:: python - - import os - from pep517.envbuild import build_wheel, build_sdist - - src = 'path/to/source' # Folder containing 'pyproject.toml' - destination = 'also/a/folder' - whl_filename = build_wheel(src, destination) - assert os.path.isfile(os.path.join(destination, whl_filename)) - - targz_filename = build_sdist(src, destination) - assert os.path.isfile(os.path.join(destination, targz_filename)) - -To test the build backend for a project, run in a system shell: - -.. code-block:: shell - - python3 -m pep517.check path/to/source # source dir containing pyproject.toml - -To build a backend into source and/or binary distributions, run in a shell: - -.. code-block:: shell - - python -m pep517.build path/to/source # source dir containing pyproject.toml - -All of this high-level functionality is deprecated. diff --git a/src/pep517/build.py b/src/pep517/build.py deleted file mode 100644 index b30909c..0000000 --- a/src/pep517/build.py +++ /dev/null @@ -1,126 +0,0 @@ -"""Build a project using PEP 517 hooks. -""" -import argparse -import logging -import os -import shutil -import tempfile - -from ._compat import tomllib -from .envbuild import BuildEnvironment -from .wrappers import Pep517HookCaller - -log = logging.getLogger(__name__) - - -def validate_system(system): - """ - Ensure build system has the requisite fields. - """ - required = {'requires', 'build-backend'} - if not (required <= set(system)): - message = "Missing required fields: {missing}".format( - missing=required-set(system), - ) - raise ValueError(message) - - -def load_system(source_dir): - """ - Load the build system from a source dir (pyproject.toml). - """ - pyproject = os.path.join(source_dir, 'pyproject.toml') - with open(pyproject, 'rb') as f: - pyproject_data = tomllib.load(f) - return pyproject_data['build-system'] - - -def compat_system(source_dir): - """ - Given a source dir, attempt to get a build system backend - and requirements from pyproject.toml. Fallback to - setuptools but only if the file was not found or a build - system was not indicated. - """ - try: - system = load_system(source_dir) - except (FileNotFoundError, KeyError): - system = {} - system.setdefault( - 'build-backend', - 'setuptools.build_meta:__legacy__', - ) - system.setdefault('requires', ['setuptools', 'wheel']) - return system - - -def _do_build(hooks, env, dist, dest): - get_requires_name = 'get_requires_for_build_{dist}'.format(**locals()) - get_requires = getattr(hooks, get_requires_name) - reqs = get_requires({}) - log.info('Got build requires: %s', reqs) - - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - - with tempfile.TemporaryDirectory() as td: - log.info('Trying to build %s in %s', dist, td) - build_name = 'build_{dist}'.format(**locals()) - build = getattr(hooks, build_name) - filename = build(td, {}) - source = os.path.join(td, filename) - shutil.move(source, os.path.join(dest, os.path.basename(filename))) - - -def build(source_dir, dist, dest=None, system=None): - system = system or load_system(source_dir) - dest = os.path.join(source_dir, dest or 'dist') - os.makedirs(dest, exist_ok=True) - - validate_system(system) - hooks = Pep517HookCaller( - source_dir, system['build-backend'], system.get('backend-path') - ) - - with BuildEnvironment() as env: - env.pip_install(system['requires']) - _do_build(hooks, env, dist, dest) - - -parser = argparse.ArgumentParser() -parser.add_argument( - 'source_dir', - help="A directory containing pyproject.toml", -) -parser.add_argument( - '--binary', '-b', - action='store_true', - default=False, -) -parser.add_argument( - '--source', '-s', - action='store_true', - default=False, -) -parser.add_argument( - '--out-dir', '-o', - help="Destination in which to save the builds relative to source dir", -) - - -def main(args): - log.warning('pep517.build is deprecated. ' - 'Consider switching to https://pypi.org/project/build/') - - # determine which dists to build - dists = list(filter(None, ( - 'sdist' if args.source or not args.binary else None, - 'wheel' if args.binary or not args.source else None, - ))) - - for dist in dists: - build(args.source_dir, dist, args.out_dir) - - -if __name__ == '__main__': - main(parser.parse_args()) diff --git a/src/pep517/check.py b/src/pep517/check.py deleted file mode 100644 index b79f627..0000000 --- a/src/pep517/check.py +++ /dev/null @@ -1,207 +0,0 @@ -"""Check a project and backend by attempting to build using PEP 517 hooks. -""" -import argparse -import logging -import os -import shutil -import sys -import tarfile -import zipfile -from os.path import isfile -from os.path import join as pjoin -from subprocess import CalledProcessError -from tempfile import mkdtemp - -from ._compat import tomllib -from .colorlog import enable_colourful_output -from .envbuild import BuildEnvironment -from .wrappers import Pep517HookCaller - -log = logging.getLogger(__name__) - - -def check_build_sdist(hooks, build_sys_requires): - with BuildEnvironment() as env: - try: - env.pip_install(build_sys_requires) - log.info('Installed static build dependencies') - except CalledProcessError: - log.error('Failed to install static build dependencies') - return False - - try: - reqs = hooks.get_requires_for_build_sdist({}) - log.info('Got build requires: %s', reqs) - except Exception: - log.error('Failure in get_requires_for_build_sdist', exc_info=True) - return False - - try: - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - except CalledProcessError: - log.error('Failed to install dynamic build dependencies') - return False - - td = mkdtemp() - log.info('Trying to build sdist in %s', td) - try: - try: - filename = hooks.build_sdist(td, {}) - log.info('build_sdist returned %r', filename) - except Exception: - log.info('Failure in build_sdist', exc_info=True) - return False - - if not filename.endswith('.tar.gz'): - log.error( - "Filename %s doesn't have .tar.gz extension", filename) - return False - - path = pjoin(td, filename) - if isfile(path): - log.info("Output file %s exists", path) - else: - log.error("Output file %s does not exist", path) - return False - - if tarfile.is_tarfile(path): - log.info("Output file is a tar file") - else: - log.error("Output file is not a tar file") - return False - - finally: - shutil.rmtree(td) - - return True - - -def check_build_wheel(hooks, build_sys_requires): - with BuildEnvironment() as env: - try: - env.pip_install(build_sys_requires) - log.info('Installed static build dependencies') - except CalledProcessError: - log.error('Failed to install static build dependencies') - return False - - try: - reqs = hooks.get_requires_for_build_wheel({}) - log.info('Got build requires: %s', reqs) - except Exception: - log.error('Failure in get_requires_for_build_sdist', exc_info=True) - return False - - try: - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - except CalledProcessError: - log.error('Failed to install dynamic build dependencies') - return False - - td = mkdtemp() - log.info('Trying to build wheel in %s', td) - try: - try: - filename = hooks.build_wheel(td, {}) - log.info('build_wheel returned %r', filename) - except Exception: - log.info('Failure in build_wheel', exc_info=True) - return False - - if not filename.endswith('.whl'): - log.error("Filename %s doesn't have .whl extension", filename) - return False - - path = pjoin(td, filename) - if isfile(path): - log.info("Output file %s exists", path) - else: - log.error("Output file %s does not exist", path) - return False - - if zipfile.is_zipfile(path): - log.info("Output file is a zip file") - else: - log.error("Output file is not a zip file") - return False - - finally: - shutil.rmtree(td) - - return True - - -def check(source_dir): - pyproject = pjoin(source_dir, 'pyproject.toml') - if isfile(pyproject): - log.info('Found pyproject.toml') - else: - log.error('Missing pyproject.toml') - return False - - try: - with open(pyproject, 'rb') as f: - pyproject_data = tomllib.load(f) - # Ensure the mandatory data can be loaded - buildsys = pyproject_data['build-system'] - requires = buildsys['requires'] - backend = buildsys['build-backend'] - backend_path = buildsys.get('backend-path') - log.info('Loaded pyproject.toml') - except (tomllib.TOMLDecodeError, KeyError): - log.error("Invalid pyproject.toml", exc_info=True) - return False - - hooks = Pep517HookCaller(source_dir, backend, backend_path) - - sdist_ok = check_build_sdist(hooks, requires) - wheel_ok = check_build_wheel(hooks, requires) - - if not sdist_ok: - log.warning('Sdist checks failed; scroll up to see') - if not wheel_ok: - log.warning('Wheel checks failed') - - return sdist_ok - - -def main(argv=None): - log.warning('pep517.check is deprecated. ' - 'Consider switching to https://pypi.org/project/build/') - - ap = argparse.ArgumentParser() - ap.add_argument( - 'source_dir', - help="A directory containing pyproject.toml") - args = ap.parse_args(argv) - - enable_colourful_output() - - ok = check(args.source_dir) - - if ok: - print(ansi('Checks passed', 'green')) - else: - print(ansi('Checks failed', 'red')) - sys.exit(1) - - -ansi_codes = { - 'reset': '\x1b[0m', - 'bold': '\x1b[1m', - 'red': '\x1b[31m', - 'green': '\x1b[32m', -} - - -def ansi(s, attr): - if os.name != 'nt' and sys.stdout.isatty(): - return ansi_codes[attr] + str(s) + ansi_codes['reset'] - else: - return str(s) - - -if __name__ == '__main__': - main() diff --git a/src/pep517/colorlog.py b/src/pep517/colorlog.py deleted file mode 100644 index 66310a7..0000000 --- a/src/pep517/colorlog.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Nicer log formatting with colours. - -Code copied from Tornado, Apache licensed. -""" -# Copyright 2012 Facebook -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import sys - -try: - import curses -except ImportError: - curses = None - - -def _stderr_supports_color(): - color = False - if curses and hasattr(sys.stderr, 'isatty') and sys.stderr.isatty(): - try: - curses.setupterm() - if curses.tigetnum("colors") > 0: - color = True - except Exception: - pass - return color - - -class LogFormatter(logging.Formatter): - """Log formatter with colour support - """ - DEFAULT_COLORS = { - logging.INFO: 2, # Green - logging.WARNING: 3, # Yellow - logging.ERROR: 1, # Red - logging.CRITICAL: 1, - } - - def __init__(self, color=True, datefmt=None): - r""" - :arg bool color: Enables color support. - :arg string fmt: Log message format. - It will be applied to the attributes dict of log records. The - text between ``%(color)s`` and ``%(end_color)s`` will be colored - depending on the level if color support is on. - :arg dict colors: color mappings from logging level to terminal color - code - :arg string datefmt: Datetime format. - Used for formatting ``(asctime)`` placeholder in ``prefix_fmt``. - .. versionchanged:: 3.2 - Added ``fmt`` and ``datefmt`` arguments. - """ - logging.Formatter.__init__(self, datefmt=datefmt) - self._colors = {} - if color and _stderr_supports_color(): - # The curses module has some str/bytes confusion in - # python3. Until version 3.2.3, most methods return - # bytes, but only accept strings. In addition, we want to - # output these strings with the logging module, which - # works with unicode strings. The explicit calls to - # unicode() below are harmless in python2 but will do the - # right conversion in python 3. - fg_color = (curses.tigetstr("setaf") or - curses.tigetstr("setf") or "") - - for levelno, code in self.DEFAULT_COLORS.items(): - self._colors[levelno] = str( - curses.tparm(fg_color, code), "ascii") - self._normal = str(curses.tigetstr("sgr0"), "ascii") - - scr = curses.initscr() - self.termwidth = scr.getmaxyx()[1] - curses.endwin() - else: - self._normal = '' - # Default width is usually 80, but too wide is - # worse than too narrow - self.termwidth = 70 - - def formatMessage(self, record): - mlen = len(record.message) - right_text = '{initial}-{name}'.format(initial=record.levelname[0], - name=record.name) - if mlen + len(right_text) < self.termwidth: - space = ' ' * (self.termwidth - (mlen + len(right_text))) - else: - space = ' ' - - if record.levelno in self._colors: - start_color = self._colors[record.levelno] - end_color = self._normal - else: - start_color = end_color = '' - - return record.message + space + start_color + right_text + end_color - - -def enable_colourful_output(level=logging.INFO): - handler = logging.StreamHandler() - handler.setFormatter(LogFormatter()) - logging.root.addHandler(handler) - logging.root.setLevel(level) diff --git a/src/pep517/dirtools.py b/src/pep517/dirtools.py deleted file mode 100644 index 3eff4d8..0000000 --- a/src/pep517/dirtools.py +++ /dev/null @@ -1,19 +0,0 @@ -import io -import os -import zipfile - - -def dir_to_zipfile(root): - """Construct an in-memory zip file for a directory.""" - buffer = io.BytesIO() - zip_file = zipfile.ZipFile(buffer, 'w') - for root, dirs, files in os.walk(root): - for path in dirs: - fs_path = os.path.join(root, path) - rel_path = os.path.relpath(fs_path, root) - zip_file.writestr(rel_path + '/', '') - for path in files: - fs_path = os.path.join(root, path) - rel_path = os.path.relpath(fs_path, root) - zip_file.write(fs_path, rel_path) - return zip_file diff --git a/src/pep517/envbuild.py b/src/pep517/envbuild.py deleted file mode 100644 index c0415c4..0000000 --- a/src/pep517/envbuild.py +++ /dev/null @@ -1,170 +0,0 @@ -"""Build wheels/sdists by installing build deps to a temporary environment. -""" - -import logging -import os -import shutil -import sys -from subprocess import check_call -from sysconfig import get_paths -from tempfile import mkdtemp - -from ._compat import tomllib -from .wrappers import LoggerWrapper, Pep517HookCaller - -log = logging.getLogger(__name__) - - -def _load_pyproject(source_dir): - with open( - os.path.join(source_dir, 'pyproject.toml'), - 'rb', - ) as f: - pyproject_data = tomllib.load(f) - buildsys = pyproject_data['build-system'] - return ( - buildsys['requires'], - buildsys['build-backend'], - buildsys.get('backend-path'), - ) - - -class BuildEnvironment: - """Context manager to install build deps in a simple temporary environment - - Based on code I wrote for pip, which is MIT licensed. - """ - # Copyright (c) 2008-2016 The pip developers (see AUTHORS.txt file) - # - # Permission is hereby granted, free of charge, to any person obtaining - # a copy of this software and associated documentation files (the - # "Software"), to deal in the Software without restriction, including - # without limitation the rights to use, copy, modify, merge, publish, - # distribute, sublicense, and/or sell copies of the Software, and to - # permit persons to whom the Software is furnished to do so, subject to - # the following conditions: - # - # The above copyright notice and this permission notice shall be - # included in all copies or substantial portions of the Software. - # - # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - path = None - - def __init__(self, cleanup=True): - self._cleanup = cleanup - - def __enter__(self): - self.path = mkdtemp(prefix='pep517-build-env-') - log.info('Temporary build environment: %s', self.path) - - self.save_path = os.environ.get('PATH', None) - self.save_pythonpath = os.environ.get('PYTHONPATH', None) - - install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix' - install_dirs = get_paths(install_scheme, vars={ - 'base': self.path, - 'platbase': self.path, - }) - - scripts = install_dirs['scripts'] - if self.save_path: - os.environ['PATH'] = scripts + os.pathsep + self.save_path - else: - os.environ['PATH'] = scripts + os.pathsep + os.defpath - - if install_dirs['purelib'] == install_dirs['platlib']: - lib_dirs = install_dirs['purelib'] - else: - lib_dirs = install_dirs['purelib'] + os.pathsep + \ - install_dirs['platlib'] - if self.save_pythonpath: - os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ - self.save_pythonpath - else: - os.environ['PYTHONPATH'] = lib_dirs - - return self - - def pip_install(self, reqs): - """Install dependencies into this env by calling pip in a subprocess""" - if not reqs: - return - log.info('Calling pip to install %s', reqs) - cmd = [ - sys.executable, '-m', 'pip', 'install', '--ignore-installed', - '--prefix', self.path] + list(reqs) - check_call( - cmd, - stdout=LoggerWrapper(log, logging.INFO), - stderr=LoggerWrapper(log, logging.ERROR), - ) - - def __exit__(self, exc_type, exc_val, exc_tb): - needs_cleanup = ( - self._cleanup and - self.path is not None and - os.path.isdir(self.path) - ) - if needs_cleanup: - shutil.rmtree(self.path) - - if self.save_path is None: - os.environ.pop('PATH', None) - else: - os.environ['PATH'] = self.save_path - - if self.save_pythonpath is None: - os.environ.pop('PYTHONPATH', None) - else: - os.environ['PYTHONPATH'] = self.save_pythonpath - - -def build_wheel(source_dir, wheel_dir, config_settings=None): - """Build a wheel from a source directory using PEP 517 hooks. - - :param str source_dir: Source directory containing pyproject.toml - :param str wheel_dir: Target directory to create wheel in - :param dict config_settings: Options to pass to build backend - - This is a blocking function which will run pip in a subprocess to install - build requirements. - """ - if config_settings is None: - config_settings = {} - requires, backend, backend_path = _load_pyproject(source_dir) - hooks = Pep517HookCaller(source_dir, backend, backend_path) - - with BuildEnvironment() as env: - env.pip_install(requires) - reqs = hooks.get_requires_for_build_wheel(config_settings) - env.pip_install(reqs) - return hooks.build_wheel(wheel_dir, config_settings) - - -def build_sdist(source_dir, sdist_dir, config_settings=None): - """Build an sdist from a source directory using PEP 517 hooks. - - :param str source_dir: Source directory containing pyproject.toml - :param str sdist_dir: Target directory to place sdist in - :param dict config_settings: Options to pass to build backend - - This is a blocking function which will run pip in a subprocess to install - build requirements. - """ - if config_settings is None: - config_settings = {} - requires, backend, backend_path = _load_pyproject(source_dir) - hooks = Pep517HookCaller(source_dir, backend, backend_path) - - with BuildEnvironment() as env: - env.pip_install(requires) - reqs = hooks.get_requires_for_build_sdist(config_settings) - env.pip_install(reqs) - return hooks.build_sdist(sdist_dir, config_settings) diff --git a/src/pep517/meta.py b/src/pep517/meta.py deleted file mode 100644 index 4afc3c0..0000000 --- a/src/pep517/meta.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Build metadata for a project using PEP 517 hooks. -""" -import argparse -import functools -import logging -import os -import shutil -import tempfile - -try: - import importlib.metadata as imp_meta -except ImportError: - import importlib_metadata as imp_meta - -try: - from zipfile import Path -except ImportError: - from zipp import Path - -from .build import compat_system, load_system, validate_system -from .dirtools import dir_to_zipfile -from .envbuild import BuildEnvironment -from .wrappers import Pep517HookCaller, quiet_subprocess_runner - -log = logging.getLogger(__name__) - - -def _prep_meta(hooks, env, dest): - reqs = hooks.get_requires_for_build_wheel({}) - log.info('Got build requires: %s', reqs) - - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - - with tempfile.TemporaryDirectory() as td: - log.info('Trying to build metadata in %s', td) - filename = hooks.prepare_metadata_for_build_wheel(td, {}) - source = os.path.join(td, filename) - shutil.move(source, os.path.join(dest, os.path.basename(filename))) - - -def build(source_dir='.', dest=None, system=None): - system = system or load_system(source_dir) - dest = os.path.join(source_dir, dest or 'dist') - os.makedirs(dest, exist_ok=True) - validate_system(system) - hooks = Pep517HookCaller( - source_dir, system['build-backend'], system.get('backend-path') - ) - - with hooks.subprocess_runner(quiet_subprocess_runner): - with BuildEnvironment() as env: - env.pip_install(system['requires']) - _prep_meta(hooks, env, dest) - - -def build_as_zip(builder=build): - with tempfile.TemporaryDirectory() as out_dir: - builder(dest=out_dir) - return dir_to_zipfile(out_dir) - - -def load(root): - """ - Given a source directory (root) of a package, - return an importlib.metadata.Distribution object - with metadata build from that package. - """ - root = os.path.expanduser(root) - system = compat_system(root) - builder = functools.partial(build, source_dir=root, system=system) - path = Path(build_as_zip(builder)) - return imp_meta.PathDistribution(path) - - -parser = argparse.ArgumentParser() -parser.add_argument( - 'source_dir', - help="A directory containing pyproject.toml", -) -parser.add_argument( - '--out-dir', '-o', - help="Destination in which to save the builds relative to source dir", -) - - -def main(): - args = parser.parse_args() - build(args.source_dir, args.out_dir) - - -if __name__ == '__main__': - main() diff --git a/tests/test_build.py b/tests/test_build.py deleted file mode 100644 index 2a7c2bc..0000000 --- a/tests/test_build.py +++ /dev/null @@ -1,27 +0,0 @@ -import pytest - -from pep517 import build - - -def system(*args): - return dict.fromkeys(args) - - -class TestValidateSystem: - def test_missing(self): - with pytest.raises(ValueError): - build.validate_system(system()) - with pytest.raises(ValueError): - build.validate_system(system('requires')) - with pytest.raises(ValueError): - build.validate_system(system('build-backend')) - with pytest.raises(ValueError): - build.validate_system(system('other')) - - def test_missing_and_extra(self): - with pytest.raises(ValueError): - build.validate_system(system('build-backend', 'other')) - - def test_satisfied(self): - build.validate_system(system('build-backend', 'requires')) - build.validate_system(system('build-backend', 'requires', 'other')) diff --git a/tests/test_envbuild.py b/tests/test_envbuild.py deleted file mode 100644 index 3a85c29..0000000 --- a/tests/test_envbuild.py +++ /dev/null @@ -1,39 +0,0 @@ -import tarfile -import zipfile -from os.path import abspath, dirname -from os.path import join as pjoin -from unittest.mock import call, patch - -from testpath import assert_isfile, modified_env -from testpath.tempdir import TemporaryDirectory - -from pep517.envbuild import BuildEnvironment, build_sdist, build_wheel - -SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') -BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') - - -@patch.object(BuildEnvironment, 'pip_install') -def test_build_wheel(mock_pip_install): - with modified_env({'PYTHONPATH': BUILDSYS_PKGS}), \ - TemporaryDirectory() as outdir: - filename = build_wheel(pjoin(SAMPLES_DIR, 'pkg1'), outdir) - assert_isfile(pjoin(outdir, filename)) - assert zipfile.is_zipfile(pjoin(outdir, filename)) - - assert mock_pip_install.call_count == 2 - assert mock_pip_install.call_args_list[0] == call(['eg_buildsys']) - assert mock_pip_install.call_args_list[1] == call(['wheelwright']) - - -@patch.object(BuildEnvironment, 'pip_install') -def test_build_sdist(mock_pip_install): - with modified_env({'PYTHONPATH': BUILDSYS_PKGS}), \ - TemporaryDirectory() as outdir: - filename = build_sdist(pjoin(SAMPLES_DIR, 'pkg1'), outdir) - assert_isfile(pjoin(outdir, filename)) - assert tarfile.is_tarfile(pjoin(outdir, filename)) - - assert mock_pip_install.call_count == 2 - assert mock_pip_install.call_args_list[0] == call(['eg_buildsys']) - assert mock_pip_install.call_args_list[1] == call(['frog']) diff --git a/tests/test_meta.py b/tests/test_meta.py deleted file mode 100644 index ddd219e..0000000 --- a/tests/test_meta.py +++ /dev/null @@ -1,26 +0,0 @@ -import re - -from pep517 import meta - - -def test_meta_for_this_package(): - dist = meta.load('.') - assert re.match(r'[\d.]+', dist.version) - assert dist.metadata['Name'] == 'pep517' - - -def test_classic_package(tmpdir): - (tmpdir / 'setup.py').write_text( - 'from distutils.core import setup; setup(name="foo", version="1.0")', - encoding='utf-8', - ) - dist = meta.load(str(tmpdir)) - assert dist.version == '1.0' - assert dist.metadata['Name'] == 'foo' - - -def test_meta_output(capfd): - """load shouldn't emit any output""" - meta.load('.') - captured = capfd.readouterr() - assert captured.out == captured.err == '' From 42fe339ff2510d18f21939f2311be7bbc56580ae Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 21:02:48 -0500 Subject: [PATCH 3/9] Drop the no-longer-necessary issue template This template is not going to be necessary since this project will have dropped these bits of functionality. --- issue_template.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 issue_template.md diff --git a/issue_template.md b/issue_template.md deleted file mode 100644 index e2986ff..0000000 --- a/issue_template.md +++ /dev/null @@ -1,4 +0,0 @@ - From 99ae28fe4550e217c2d148ff307b206756137149 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 21:08:58 -0500 Subject: [PATCH 4/9] Rename the project to `pyproject-hooks` This more accurately reflects what this project is for. --- .bumpversion.cfg | 2 +- README.rst | 4 ++-- doc/callhooks.rst | 2 +- doc/conf.py | 2 +- doc/index.rst | 4 ++-- pyproject.toml | 5 +++-- src/{pep517 => pyproject_hooks}/__init__.py | 0 src/{pep517 => pyproject_hooks}/_compat.py | 0 src/{pep517 => pyproject_hooks}/in_process/__init__.py | 0 src/{pep517 => pyproject_hooks}/in_process/_in_process.py | 0 src/{pep517 => pyproject_hooks}/wrappers.py | 0 tests/test_call_hooks.py | 2 +- tests/test_hook_fallbacks.py | 2 +- tests/test_inplace_hooks.py | 2 +- 14 files changed, 13 insertions(+), 12 deletions(-) rename src/{pep517 => pyproject_hooks}/__init__.py (100%) rename src/{pep517 => pyproject_hooks}/_compat.py (100%) rename src/{pep517 => pyproject_hooks}/in_process/__init__.py (100%) rename src/{pep517 => pyproject_hooks}/in_process/_in_process.py (100%) rename src/{pep517 => pyproject_hooks}/wrappers.py (100%) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cb59586..8fd02a3 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -3,4 +3,4 @@ current_version = 0.13.0 commit = True tag = True -[bumpversion:file:src/pep517/__init__.py] +[bumpversion:file:src/pyproject_hooks/__init__.py] diff --git a/README.rst b/README.rst index 77f6c5f..18645d3 100644 --- a/README.rst +++ b/README.rst @@ -23,7 +23,7 @@ Usage—you are responsible for ensuring build requirements are available: import os import tomli - from pep517.wrappers import Pep517HookCaller + from pyproject_hooks.wrappers import Pep517HookCaller src = 'path/to/source' # Folder containing 'pyproject.toml' with open(os.path.join(src, 'pyproject.toml'), 'rb') as f: @@ -34,7 +34,7 @@ Usage—you are responsible for ensuring build requirements are available: # an environment where they are available. hooks = Pep517HookCaller( - src, + src, build_backend=build_sys['build-backend'], backend_path=build_sys.get('backend-path'), ) diff --git a/doc/callhooks.rst b/doc/callhooks.rst index 23ee06c..8e27c44 100644 --- a/doc/callhooks.rst +++ b/doc/callhooks.rst @@ -1,7 +1,7 @@ API reference ============= -.. module:: pep517 +.. module:: pyproject_hooks Calling the build system ------------------------ diff --git a/doc/conf.py b/doc/conf.py index 2bb968c..bdac2f7 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -18,7 +18,7 @@ # -- Project information ----------------------------------------------------- -project = 'pep517' +project = 'pyproject-hooks' copyright = '2020, Thomas Kluyver' author = 'Thomas Kluyver' diff --git a/doc/index.rst b/doc/index.rst index b564e9b..cae08ea 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,5 +1,5 @@ -pep517 -====== +pyproject-hooks +=============== This package provides an API to call the hooks defined in :pep:`517`. diff --git a/pyproject.toml b/pyproject.toml index 132893d..e19c673 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,10 +3,11 @@ requires = ["flit_core >=3.2,<4"] build-backend = "flit_core.buildapi" [tool.flit.metadata] -module = "pep517" +module = "pyproject_hooks" +dist-name = "pyproject-hooks" author = "Thomas Kluyver" author-email = "thomas@kluyver.me.uk" -home-page = "https://github.com/pypa/pep517" +home-page = "https://github.com/pypa/pyproject-hooks" description-file = "README.rst" requires = [ "tomli >=1.1.0;python_version<'3.11'", diff --git a/src/pep517/__init__.py b/src/pyproject_hooks/__init__.py similarity index 100% rename from src/pep517/__init__.py rename to src/pyproject_hooks/__init__.py diff --git a/src/pep517/_compat.py b/src/pyproject_hooks/_compat.py similarity index 100% rename from src/pep517/_compat.py rename to src/pyproject_hooks/_compat.py diff --git a/src/pep517/in_process/__init__.py b/src/pyproject_hooks/in_process/__init__.py similarity index 100% rename from src/pep517/in_process/__init__.py rename to src/pyproject_hooks/in_process/__init__.py diff --git a/src/pep517/in_process/_in_process.py b/src/pyproject_hooks/in_process/_in_process.py similarity index 100% rename from src/pep517/in_process/_in_process.py rename to src/pyproject_hooks/in_process/_in_process.py diff --git a/src/pep517/wrappers.py b/src/pyproject_hooks/wrappers.py similarity index 100% rename from src/pep517/wrappers.py rename to src/pyproject_hooks/wrappers.py diff --git a/tests/test_call_hooks.py b/tests/test_call_hooks.py index 9f73d50..d0d7e96 100644 --- a/tests/test_call_hooks.py +++ b/tests/test_call_hooks.py @@ -11,7 +11,7 @@ from testpath import assert_isfile, modified_env from testpath.tempdir import TemporaryDirectory, TemporaryWorkingDirectory -from pep517.wrappers import ( +from pyproject_hooks.wrappers import ( BackendUnavailable, Pep517HookCaller, UnsupportedOperation, diff --git a/tests/test_hook_fallbacks.py b/tests/test_hook_fallbacks.py index cdfd581..2686542 100644 --- a/tests/test_hook_fallbacks.py +++ b/tests/test_hook_fallbacks.py @@ -6,7 +6,7 @@ from testpath import assert_isfile, modified_env from testpath.tempdir import TemporaryDirectory -from pep517.wrappers import HookMissing, Pep517HookCaller +from pyproject_hooks.wrappers import HookMissing, Pep517HookCaller SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') diff --git a/tests/test_inplace_hooks.py b/tests/test_inplace_hooks.py index 40c9f9d..f3436fc 100644 --- a/tests/test_inplace_hooks.py +++ b/tests/test_inplace_hooks.py @@ -5,7 +5,7 @@ import tomli from testpath import modified_env -from pep517.wrappers import BackendInvalid, Pep517HookCaller +from pyproject_hooks.wrappers import BackendInvalid, Pep517HookCaller SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') From 709ed1377c3bd0e98f556645036e61c03d6e0cbc Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 21:14:13 -0500 Subject: [PATCH 5/9] Rename `Pep517HookCaller` to `BuildBackendHookCaller` This is a better name for the functionality provided by this class. --- README.rst | 4 ++-- doc/callhooks.rst | 6 +++--- doc/changelog.rst | 2 +- src/pyproject_hooks/wrappers.py | 4 ++-- tests/test_call_hooks.py | 4 ++-- tests/test_hook_fallbacks.py | 4 ++-- tests/test_inplace_hooks.py | 8 ++++---- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index 18645d3..51f6b85 100644 --- a/README.rst +++ b/README.rst @@ -23,7 +23,7 @@ Usage—you are responsible for ensuring build requirements are available: import os import tomli - from pyproject_hooks.wrappers import Pep517HookCaller + from pyproject_hooks.wrappers import BuildBackendHookCaller src = 'path/to/source' # Folder containing 'pyproject.toml' with open(os.path.join(src, 'pyproject.toml'), 'rb') as f: @@ -33,7 +33,7 @@ Usage—you are responsible for ensuring build requirements are available: # The caller is responsible for installing these and running the hooks in # an environment where they are available. - hooks = Pep517HookCaller( + hooks = BuildBackendHookCaller( src, build_backend=build_sys['build-backend'], backend_path=build_sys.get('backend-path'), diff --git a/doc/callhooks.rst b/doc/callhooks.rst index 8e27c44..0b057bb 100644 --- a/doc/callhooks.rst +++ b/doc/callhooks.rst @@ -6,7 +6,7 @@ API reference Calling the build system ------------------------ -.. autoclass:: Pep517HookCaller +.. autoclass:: BuildBackendHookCaller .. automethod:: get_requires_for_build_sdist @@ -29,8 +29,8 @@ Calling the build system Subprocess runners ------------------ -These functions may be provided when creating :class:`Pep517HookCaller`, -or to :meth:`Pep517HookCaller.subprocess_runner`. +These functions may be provided when creating :class:`BuildBackendHookCaller`, +or to :meth:`BuildBackendHookCaller.subprocess_runner`. .. autofunction:: default_subprocess_runner diff --git a/doc/changelog.rst b/doc/changelog.rst index 337beb7..f74c2f1 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -50,7 +50,7 @@ Changelog - Deprecated the higher level API which handles creating an environment and installing build dependencies. This was not very complete, and the `PyPA build project `_ is designed for this use case. -- New ``python_executable`` parameter for :class:`.Pep517HookCaller` to run hooks +- New ``python_executable`` parameter for :class:`.BuildBackendHookCaller` to run hooks with a different Python interpreter. - Fix for locating the script to run in the subprocess in some scenarios. - Fix example in README to get ``build-backend`` correctly. diff --git a/src/pyproject_hooks/wrappers.py b/src/pyproject_hooks/wrappers.py index 987a62a..e145003 100644 --- a/src/pyproject_hooks/wrappers.py +++ b/src/pyproject_hooks/wrappers.py @@ -17,7 +17,7 @@ 'UnsupportedOperation', 'default_subprocess_runner', 'quiet_subprocess_runner', - 'Pep517HookCaller', + 'BuildBackendHookCaller', ] @@ -100,7 +100,7 @@ def norm_and_check(source_tree, requested): return abs_requested -class Pep517HookCaller: +class BuildBackendHookCaller: """A wrapper around a source directory to be built with a PEP 517 backend. :param source_dir: The path to the source directory, containing diff --git a/tests/test_call_hooks.py b/tests/test_call_hooks.py index d0d7e96..5341adc 100644 --- a/tests/test_call_hooks.py +++ b/tests/test_call_hooks.py @@ -13,7 +13,7 @@ from pyproject_hooks.wrappers import ( BackendUnavailable, - Pep517HookCaller, + BuildBackendHookCaller, UnsupportedOperation, default_subprocess_runner, ) @@ -26,7 +26,7 @@ def get_hooks(pkg, **kwargs): source_dir = pjoin(SAMPLES_DIR, pkg) with open(pjoin(source_dir, 'pyproject.toml'), 'rb') as f: data = tomli.load(f) - return Pep517HookCaller( + return BuildBackendHookCaller( source_dir, data['build-system']['build-backend'], **kwargs ) diff --git a/tests/test_hook_fallbacks.py b/tests/test_hook_fallbacks.py index 2686542..b34ae10 100644 --- a/tests/test_hook_fallbacks.py +++ b/tests/test_hook_fallbacks.py @@ -6,7 +6,7 @@ from testpath import assert_isfile, modified_env from testpath.tempdir import TemporaryDirectory -from pyproject_hooks.wrappers import HookMissing, Pep517HookCaller +from pyproject_hooks.wrappers import BuildBackendHookCaller, HookMissing SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') @@ -16,7 +16,7 @@ def get_hooks(pkg): source_dir = pjoin(SAMPLES_DIR, pkg) with open(pjoin(source_dir, 'pyproject.toml'), 'rb') as f: data = tomli.load(f) - return Pep517HookCaller(source_dir, data['build-system']['build-backend']) + return BuildBackendHookCaller(source_dir, data['build-system']['build-backend']) def test_get_requires_for_build_wheel(): diff --git a/tests/test_inplace_hooks.py b/tests/test_inplace_hooks.py index f3436fc..6b9723a 100644 --- a/tests/test_inplace_hooks.py +++ b/tests/test_inplace_hooks.py @@ -5,7 +5,7 @@ import tomli from testpath import modified_env -from pyproject_hooks.wrappers import BackendInvalid, Pep517HookCaller +from pyproject_hooks.wrappers import BackendInvalid, BuildBackendHookCaller SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') @@ -20,7 +20,7 @@ def get_hooks(pkg, backend=None, path=None): backend = data['build-system']['build-backend'] if path is None: path = data['build-system']['backend-path'] - return Pep517HookCaller(source_dir, backend, path) + return BuildBackendHookCaller(source_dir, backend, path) @pytest.mark.parametrize('backend_path', [ @@ -28,7 +28,7 @@ def get_hooks(pkg, backend=None, path=None): ['../pkg1', 'subdir/..'], ]) def test_backend_path_within_tree(backend_path): - Pep517HookCaller(SOURCE_DIR, 'dummy', backend_path) + BuildBackendHookCaller(SOURCE_DIR, 'dummy', backend_path) @pytest.mark.parametrize('backend_path', [ @@ -40,7 +40,7 @@ def test_backend_path_within_tree(backend_path): def test_backend_out_of_tree(backend_path): # TODO: Do we want to insist on ValueError, or invent another exception? with pytest.raises(Exception): - Pep517HookCaller(SOURCE_DIR, 'dummy', backend_path) + BuildBackendHookCaller(SOURCE_DIR, 'dummy', backend_path) def test_intree_backend(): From d234217bbf60627b98b1582daf0bad74555c0cab Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 21:18:06 -0500 Subject: [PATCH 6/9] Expose all functionality only via the top level name This makes the imports for this package cleaner. --- src/pyproject_hooks/__init__.py | 21 +++++++++++++++++-- src/pyproject_hooks/{wrappers.py => _impl.py} | 10 --------- tests/test_call_hooks.py | 2 +- tests/test_hook_fallbacks.py | 2 +- tests/test_inplace_hooks.py | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) rename src/pyproject_hooks/{wrappers.py => _impl.py} (98%) diff --git a/src/pyproject_hooks/__init__.py b/src/pyproject_hooks/__init__.py index 38ea0f5..b6684aa 100644 --- a/src/pyproject_hooks/__init__.py +++ b/src/pyproject_hooks/__init__.py @@ -1,6 +1,23 @@ """Wrappers to build Python packages using PEP 517 hooks """ -__version__ = '0.13.0' +from ._impl import ( + BackendInvalid, + BackendUnavailable, + BuildBackendHookCaller, + HookMissing, + UnsupportedOperation, + default_subprocess_runner, + quiet_subprocess_runner, +) -from .wrappers import * # noqa: F401, F403 +__version__ = '0.13.0' +__all__ = [ + 'BackendUnavailable', + 'BackendInvalid', + 'HookMissing', + 'UnsupportedOperation', + 'default_subprocess_runner', + 'quiet_subprocess_runner', + 'BuildBackendHookCaller', +] diff --git a/src/pyproject_hooks/wrappers.py b/src/pyproject_hooks/_impl.py similarity index 98% rename from src/pyproject_hooks/wrappers.py rename to src/pyproject_hooks/_impl.py index e145003..df3019a 100644 --- a/src/pyproject_hooks/wrappers.py +++ b/src/pyproject_hooks/_impl.py @@ -10,16 +10,6 @@ from .in_process import _in_proc_script_path -__all__ = [ - 'BackendUnavailable', - 'BackendInvalid', - 'HookMissing', - 'UnsupportedOperation', - 'default_subprocess_runner', - 'quiet_subprocess_runner', - 'BuildBackendHookCaller', -] - def write_json(obj, path, **kwargs): with open(path, 'w', encoding='utf-8') as f: diff --git a/tests/test_call_hooks.py b/tests/test_call_hooks.py index 5341adc..c3d690b 100644 --- a/tests/test_call_hooks.py +++ b/tests/test_call_hooks.py @@ -11,7 +11,7 @@ from testpath import assert_isfile, modified_env from testpath.tempdir import TemporaryDirectory, TemporaryWorkingDirectory -from pyproject_hooks.wrappers import ( +from pyproject_hooks import ( BackendUnavailable, BuildBackendHookCaller, UnsupportedOperation, diff --git a/tests/test_hook_fallbacks.py b/tests/test_hook_fallbacks.py index b34ae10..40a2fc8 100644 --- a/tests/test_hook_fallbacks.py +++ b/tests/test_hook_fallbacks.py @@ -6,7 +6,7 @@ from testpath import assert_isfile, modified_env from testpath.tempdir import TemporaryDirectory -from pyproject_hooks.wrappers import BuildBackendHookCaller, HookMissing +from pyproject_hooks import BuildBackendHookCaller, HookMissing SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') diff --git a/tests/test_inplace_hooks.py b/tests/test_inplace_hooks.py index 6b9723a..5e0ee57 100644 --- a/tests/test_inplace_hooks.py +++ b/tests/test_inplace_hooks.py @@ -5,7 +5,7 @@ import tomli from testpath import modified_env -from pyproject_hooks.wrappers import BackendInvalid, BuildBackendHookCaller +from pyproject_hooks import BackendInvalid, BuildBackendHookCaller SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples') BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs') From 1dfa76f93b508fb467f5d6de45c973cd8530e012 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Fri, 28 Oct 2022 21:19:44 -0500 Subject: [PATCH 7/9] Make the `in_process` subpackage as private, via a leading underscore This makes it clearer that this sub-package is intended to be a private implementation detail. --- src/pyproject_hooks/_impl.py | 2 +- src/pyproject_hooks/{in_process => _in_process}/__init__.py | 0 src/pyproject_hooks/{in_process => _in_process}/_in_process.py | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/pyproject_hooks/{in_process => _in_process}/__init__.py (100%) rename src/pyproject_hooks/{in_process => _in_process}/_in_process.py (100%) diff --git a/src/pyproject_hooks/_impl.py b/src/pyproject_hooks/_impl.py index df3019a..6720e5b 100644 --- a/src/pyproject_hooks/_impl.py +++ b/src/pyproject_hooks/_impl.py @@ -8,7 +8,7 @@ from os.path import join as pjoin from subprocess import STDOUT, check_call, check_output -from .in_process import _in_proc_script_path +from ._in_process import _in_proc_script_path def write_json(obj, path, **kwargs): diff --git a/src/pyproject_hooks/in_process/__init__.py b/src/pyproject_hooks/_in_process/__init__.py similarity index 100% rename from src/pyproject_hooks/in_process/__init__.py rename to src/pyproject_hooks/_in_process/__init__.py diff --git a/src/pyproject_hooks/in_process/_in_process.py b/src/pyproject_hooks/_in_process/_in_process.py similarity index 100% rename from src/pyproject_hooks/in_process/_in_process.py rename to src/pyproject_hooks/_in_process/_in_process.py From f97e7de07164e3ce38f08c64323511faad030d6e Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sat, 29 Oct 2022 08:57:15 -0500 Subject: [PATCH 8/9] Drop support for Python 3.6 This Python version is post-EOL. --- .github/workflows/tests.yml | 2 +- pyproject.toml | 2 +- src/pyproject_hooks/_in_process/__init__.py | 28 ++++++++------------- tox.ini | 2 +- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aea19d3..51c989e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] os: [ubuntu-latest, macos-latest, windows-latest] steps: diff --git a/pyproject.toml b/pyproject.toml index e19c673..dff4ee1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ requires = [ "importlib_metadata;python_version<'3.8'", "zipp;python_version<'3.8'", ] -requires-python = ">=3.6" +requires-python = ">=3.7" classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", diff --git a/src/pyproject_hooks/_in_process/__init__.py b/src/pyproject_hooks/_in_process/__init__.py index 281a356..917fa06 100644 --- a/src/pyproject_hooks/_in_process/__init__.py +++ b/src/pyproject_hooks/_in_process/__init__.py @@ -3,24 +3,16 @@ The subpackage should stay as empty as possible to avoid shadowing modules that the backend might import. """ -from contextlib import contextmanager -from os.path import abspath, dirname -from os.path import join as pjoin + +import importlib.resources as resources try: - import importlib.resources as resources - try: - resources.files - except AttributeError: - # Python 3.8 compatibility - def _in_proc_script_path(): - return resources.path(__package__, '_in_process.py') - else: - def _in_proc_script_path(): - return resources.as_file( - resources.files(__package__).joinpath('_in_process.py')) -except ImportError: - # Python 3.6 compatibility - @contextmanager + resources.files +except AttributeError: + # Python 3.8 compatibility + def _in_proc_script_path(): + return resources.path(__package__, '_in_process.py') +else: def _in_proc_script_path(): - yield pjoin(dirname(abspath(__file__)), '_in_process.py') + return resources.as_file( + resources.files(__package__).joinpath('_in_process.py')) diff --git a/tox.ini b/tox.ini index 354982b..40b9ecf 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py36, py37, py38, py39, py310, py311, pypy3, isort +envlist = py37, py38, py39, py310, py311, pypy3, isort isolated_build = true [testenv] From ae0c75c5492a57232fce11402518321a9a04bf4c Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 31 Oct 2022 10:54:35 +0000 Subject: [PATCH 9/9] Fix example in README --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 51f6b85..2d798c2 100644 --- a/README.rst +++ b/README.rst @@ -23,7 +23,7 @@ Usage—you are responsible for ensuring build requirements are available: import os import tomli - from pyproject_hooks.wrappers import BuildBackendHookCaller + from pyproject_hooks import BuildBackendHookCaller src = 'path/to/source' # Folder containing 'pyproject.toml' with open(os.path.join(src, 'pyproject.toml'), 'rb') as f: