diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 81656cf1..b4b2c092 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,7 @@ repos: - id: check-copyright-headers name: Check python modules for appropriate copyright headers files: ^.*\.py$ + exclude: setup\.py entry: python .pre-commit-hooks/copyright_headers.py language: system # <---- Local Hooks ------------------------------------------------------------------------------------------------ @@ -31,3 +32,15 @@ repos: rev: 22.6.0 hooks: - id: black + + # ----- Code Analysis ---------------------------------------------------------------------------------------------> + - repo: https://github.com/pycqa/flake8 + rev: '5.0.4' + hooks: + - id: flake8 + exclude: ^(\.pre-commit-hooks/.*\.py)$ + additional_dependencies: + - flake8-mypy-fork + - flake8-docstrings + - flake8-typing-imports + # <---- Code Analysis --------------------------------------------------------------------------------------------- diff --git a/noxfile.py b/noxfile.py index 4bfbf745..3bc3ee45 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,7 +1,7 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 """ -Nox session definitions +Nox session definitions. """ import datetime import os diff --git a/relenv/__main__.py b/relenv/__main__.py index ae552093..3146a848 100644 --- a/relenv/__main__.py +++ b/relenv/__main__.py @@ -1,7 +1,7 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 """ -The entrypoint into relenv +The entrypoint into relenv. """ from argparse import ArgumentParser @@ -38,7 +38,7 @@ def setup_cli(): def main(): """ - Run the relenv cli and disbatch to subcommands + Run the relenv cli and disbatch to subcommands. """ parser = setup_cli() args = parser.parse_args() diff --git a/relenv/build/__init__.py b/relenv/build/__init__.py index 412e2142..73b944ae 100644 --- a/relenv/build/__init__.py +++ b/relenv/build/__init__.py @@ -13,6 +13,9 @@ def platform_module(): + """ + Return the right module based on `sys.platform`. + """ if sys.platform == "darwin": return darwin elif sys.platform == "linux": diff --git a/relenv/build/common.py b/relenv/build/common.py index f7c35636..e0d1e9bb 100644 --- a/relenv/build/common.py +++ b/relenv/build/common.py @@ -1,8 +1,10 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 +""" +Build process common methods. +""" import logging import os.path -import codecs import hashlib import pathlib import glob @@ -31,7 +33,6 @@ get_toolchain, get_triplet, runcmd, - work_root, work_dirs, ) from relenv.relocate import main as relocate_main @@ -415,7 +416,7 @@ def valid_hash(self): @staticmethod def validate_signature(archive, signature): """ - True when the archive's signature is valid + True when the archive's signature is valid. :param archive: The path to the archive to validate :type archive: str @@ -638,7 +639,7 @@ def __init__( def set_arch(self, arch): """ - Set the architecture for the build + Set the architecture for the build. :param arch: The arch to build :type arch: str @@ -838,7 +839,7 @@ def build(self, steps=None, cleanup=True): :type steps: list, optional :param cleanup: Whether to clean up or not, defaults to True :type cleanup: bool, optional - """ + """ # noqa: D400 fails = [] events = {} waits = {} @@ -924,8 +925,9 @@ def build(self, steps=None, cleanup=True): def check_prereqs(self): """ - Check pre-requsists for build. This method verifies all requrements for - a successful build are satisfied. + Check pre-requsists for build. + + This method verifies all requrements for a successful build are satisfied. :return: Returns a list of string describing failed checks :rtype: list @@ -983,6 +985,8 @@ def __call__( def install_sysdata(mod, destfile, buildroot, toolchain): """ + Create a Relenv Python environment's sysconfigdata. + Helper method used by the `finalize` build method to create a Relenv Python environment's sysconfigdata. @@ -996,22 +1000,23 @@ def install_sysdata(mod, destfile, buildroot, toolchain): :type toolchain: str """ data = {} - fbuildroot = lambda _: _.replace(str(buildroot), "{BUILDROOT}") - ftoolchain = lambda _: _.replace(str(toolchain), "{TOOLCHAIN}") - keymap = { - "BINDIR": (fbuildroot,), - "BINLIBDEST": (fbuildroot,), - "CFLAGS": (fbuildroot, ftoolchain), - "CPPLAGS": (fbuildroot, ftoolchain), - "CXXFLAGS": (fbuildroot, ftoolchain), - "datarootdir": (fbuildroot,), - "exec_prefix": (fbuildroot,), - "LDFLAGS": (fbuildroot, ftoolchain), - "LDSHARED": (fbuildroot, ftoolchain), - "LIBDEST": (fbuildroot,), - "prefix": (fbuildroot,), - "SCRIPTDIR": (fbuildroot,), - } + fbuildroot = lambda _: _.replace(str(buildroot), "{BUILDROOT}") # noqa: E731 + ftoolchain = lambda _: _.replace(str(toolchain), "{TOOLCHAIN}") # noqa: E731 + # XXX: keymap is not used, remove it? + # keymap = { + # "BINDIR": (fbuildroot,), + # "BINLIBDEST": (fbuildroot,), + # "CFLAGS": (fbuildroot, ftoolchain), + # "CPPLAGS": (fbuildroot, ftoolchain), + # "CXXFLAGS": (fbuildroot, ftoolchain), + # "datarootdir": (fbuildroot,), + # "exec_prefix": (fbuildroot,), + # "LDFLAGS": (fbuildroot, ftoolchain), + # "LDSHARED": (fbuildroot, ftoolchain), + # "LIBDEST": (fbuildroot,), + # "prefix": (fbuildroot,), + # "SCRIPTDIR": (fbuildroot,), + # } for key in sorted(mod.build_time_vars): val = mod.build_time_vars[key] if isinstance(val, str): @@ -1031,7 +1036,7 @@ def install_sysdata(mod, destfile, buildroot, toolchain): def find_sysconfigdata(pymodules): """ - Find sysconfigdata directory for python installation + Find sysconfigdata directory for python installation. :param pymodules: Path to python modules (e.g. lib/python3.10) :type pymodules: str @@ -1047,8 +1052,9 @@ def find_sysconfigdata(pymodules): def finalize(env, dirs, logfp): """ - Run after we've fully built python. This method enhances the newly created - python with Relenv's runtime hacks. + Run after we've fully built python. + + This method enhances the newly created python with Relenv's runtime hacks. :param env: The environment dictionary :type env: dict diff --git a/relenv/build/linux.py b/relenv/build/linux.py index 8c02c12f..e7985dff 100644 --- a/relenv/build/linux.py +++ b/relenv/build/linux.py @@ -1,8 +1,10 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 +""" +The linux build process. +""" from .common import * from ..common import arches, LINUX -import textwrap ARCHES = arches[LINUX] diff --git a/relenv/build/windows.py b/relenv/build/windows.py index 09640a96..5ce5caa2 100644 --- a/relenv/build/windows.py +++ b/relenv/build/windows.py @@ -1,5 +1,8 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 +""" +The windows build process. +""" import glob import shutil import sys diff --git a/relenv/common.py b/relenv/common.py index 46675879..720857a4 100644 --- a/relenv/common.py +++ b/relenv/common.py @@ -1,7 +1,7 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 """ -Common classes and values used around relenv +Common classes and values used around relenv. """ import os import pathlib @@ -46,11 +46,14 @@ class RelenvException(Exception): """ - Base class for exeptions generated from relenv + Base class for exeptions generated from relenv. """ def build_arch(): + """ + Return the current machine. + """ machine = platform.machine() return machine.lower() @@ -199,7 +202,7 @@ def get_triplet(machine=None, plat=None): elif plat == "linux": return f"{machine}-linux-gnu" else: - raise RelenvException("Unknown platform {}".format(platform)) + raise RelenvException(f"Unknown platform {plat}") def archived_build(triplet=None): @@ -220,7 +223,7 @@ def archived_build(triplet=None): def extract_archive(to_dir, archive): """ - Extract an archive to a specific location + Extract an archive to a specific location. :param to_dir: The directory to extract to :type to_dir: str @@ -256,8 +259,9 @@ def get_download_location(url, dest): def download_url(url, dest, verbose=True): """ - Download the url to the provided destination. This method assumes the last - part of the url is a filename. (https://foo.com/bar/myfile.tar.xz) + Download the url to the provided destination. + + This method assumes the last part of the url is a filename. (https://foo.com/bar/myfile.tar.xz) :param url: The url to download :type url: str @@ -292,7 +296,7 @@ def download_url(url, dest, verbose=True): block = fin.read(10240) fin.close() fout.close() - except: + except Exception: try: os.unlink(local) except OSError: @@ -303,6 +307,8 @@ def download_url(url, dest, verbose=True): def runcmd(*args, **kwargs): """ + Run a command. + Run the provided command, raising an Exception when the command finishes with a non zero exit code. Arguments are passed through to ``subprocess.run`` diff --git a/relenv/create.py b/relenv/create.py index bbd78914..cd8aba78 100644 --- a/relenv/create.py +++ b/relenv/create.py @@ -10,7 +10,7 @@ import sys import tarfile -from .common import MODULE_DIR, RelenvException, arches, archived_build, build_arch +from .common import RelenvException, arches, archived_build, build_arch @contextlib.contextmanager @@ -44,7 +44,10 @@ def setup_parser(subparsers): """ create_subparser = subparsers.add_parser( "create", - description="Create a Relenv environment. This will create a directory of the given name with newly created Relenv environment.", + description=( + "Create a Relenv environment. This will create a directory of the given " + "name with newly created Relenv environment.", + ), ) create_subparser.set_defaults(func=main) create_subparser.add_argument("name", help="The name of the directory to create") diff --git a/relenv/fetch.py b/relenv/fetch.py index fbd1725e..c466c097 100644 --- a/relenv/fetch.py +++ b/relenv/fetch.py @@ -5,7 +5,6 @@ """ import os -import sys from .build import platform_module from .common import DATA_DIR, build_arch, download_url, get_triplet, work_dir @@ -42,4 +41,4 @@ def main(args): url = f"https://woz.io/relenv/{version}/build/{triplet}.tar.xz" builddir = work_dir("build", DATA_DIR) os.makedirs(builddir, exist_ok=True) - archive = download_url(url, builddir) + download_url(url, builddir) diff --git a/relenv/relocate.py b/relenv/relocate.py index b6eedd9c..d411d85a 100755 --- a/relenv/relocate.py +++ b/relenv/relocate.py @@ -45,7 +45,7 @@ def is_macho(path): """ - Determines whether the given file is a macho file + Determines whether the given file is a macho file. :param path: The path to the file to check :type path: str @@ -61,7 +61,7 @@ def is_macho(path): def is_elf(path): """ - Determines whether the given file is an ELF file + Determines whether the given file is an ELF file. :param path: The path to the file to check :type path: str @@ -229,7 +229,7 @@ def is_in_dir(filepath, directory): def patch_rpath(path, new_rpath, only_relative=True): """ - Patch the rpath of a given ELF file + Patch the rpath of a given ELF file. :param path: The path to an ELF file :type path: str @@ -264,7 +264,7 @@ def patch_rpath(path, new_rpath, only_relative=True): def handle_elf(path, libs, rpath_only, root=None): """ - Handle the parsing and pathcing of an ELF file + Handle the parsing and pathcing of an ELF file. :param path: The path of the ELF file :type path: str diff --git a/relenv/runtime.py b/relenv/runtime.py index 306d0a86..9e9b29a7 100644 --- a/relenv/runtime.py +++ b/relenv/runtime.py @@ -1,8 +1,7 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 """ -This code is run when initializing the python interperter in a Relenv -environment. +This code is run when initializing the python interperter in a Relenv environment. - Point Relenv's Openssl to the system installed Openssl certificate path - Make sure pip creates scripts with a shebang that points to the correct @@ -11,7 +10,6 @@ gcc. This ensures when using pip any c dependencies are compiled against the proper glibc version. """ -import collections.abc import importlib import os import pathlib @@ -34,6 +32,9 @@ def debug(string): def root(): + """ + Return the relenv module root. + """ # XXX Look for rootdir / ".relenv" if sys.platform == "win32": # /Lib/site-packages/relenv/ @@ -44,7 +45,7 @@ def root(): def _build_shebang(*args, **kwargs): """ - Build a shebang to point to the proper location + Build a shebang to point to the proper location. :return: The shebang :rtype: bytes @@ -59,6 +60,10 @@ def _build_shebang(*args, **kwargs): def get_config_var_wrapper(func): + """ + Return a wrapper to resolve paths relative to the relenv root. + """ + def wrapped(name): if name == "BINDIR": orig = func(name) @@ -77,6 +82,10 @@ def wrapped(name): def get_paths_wrapper(func, default_scheme): + """ + Return a wrapper to resolve paths relative to the relenv root. + """ + def wrapped(scheme=default_scheme, vars=None, expand=True): paths = func(scheme=scheme, vars=vars, expand=expand) if "RELENV_PIP_DIR" in os.environ: @@ -100,7 +109,7 @@ class RelenvImporter: def find_module(self, module_name, package_path=None): """ - Find a module for importing into the relenv environment + Find a module for importing into the relenv environment. :param module_name: The name of the module :type module_name: str @@ -125,7 +134,7 @@ def find_module(self, module_name, package_path=None): def load_module(self, name): """ - Load the given module + Load the given module. :param name: The module name to load :type name: str diff --git a/setup.cfg b/setup.cfg index 18c75e56..e19ebe2b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,3 +21,62 @@ include_package_data = True [options.entry_points] console_scripts = relenv = relenv.__main__:main + +[sdist] +owner = root +group = root + +[flake8] +max-line-length = 120 +exclude = + # No need to traverse our git directory + .git, + # Nox virtualenvs are also not important + .nox, + # There's no value in checking cache directories + __pycache__, + # Package build stuff + build, + dist, + # The conf file is mostly autogenerated, ignore it + docs/conf.py, + # Also ignore setup.py, it's mostly a shim + setup.py, + # Ignore our custom pre-commit hooks + .pre-commit-hooks + +ignore = + # D104 Missing docstring in public package + D104, + # D107 Missing docstring in __init__ + D107, + # D200 One-line docstring should fit on one line with quotes + D200, + # D401 First line should be in imperative mood; try rephrasing + D401, + # F403 'from import *' used; unable to detect undefined names + F403, + # F405 '*' may be undefined, or defined from star imports: * + F405 + +per-file-ignores = + # F401 imported but unused + __init__.py: F401 + # D100 Missing docstring in public module + # D103 Missing docstring in public function + noxfile.py: D100,D102,D103,D107,D212,E501 + # D100 Missing docstring in public module + docs/source/conf.py: D100 + # D102 Missing docstring in public method + # D103 Missing docstring in public function + # D107 Missing docstring in __init__ + relenv/build/common.py: D102,D103,D107 + # D100 Missing docstring in public module + # D101 Missing docstring in public class + # D102 Missing docstring in public method + # D103 Missing docstring in public function + # D105 Missing docstring in magic method + # D107 Missing docstring in __init__ + # D205 1 blank line required between summary line and description + # D415 First line should end with a period, question mark, or exclamation poin + tests/*.py: D100,D101,D102,D103,D105,D107,D205,D415 diff --git a/setup.py b/setup.py index 2468aed0..6012477f 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,3 @@ -# Copyright 2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2 #!/usr/bin/env python3 from setuptools import setup diff --git a/tests/test_build.py b/tests/test_build.py index 6c9db348..2d40b0d1 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -5,7 +5,7 @@ import pytest from relenv.build.common import Builder, verify_checksum -from relenv.common import DATA_DIR, MODULE_DIR, RelenvException +from relenv.common import DATA_DIR, RelenvException @pytest.fixture diff --git a/tests/test_create.py b/tests/test_create.py index 4e19af1a..2d5c78eb 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -47,7 +47,7 @@ def test_create_directory_exists(tmp_path): create("foo", dest=tmp_path) -def test_create_directory_exists(tmp_path): +def test_create_arches_directory_exists(tmp_path): mocked_arches = {key: [] for key in arches.keys()} with patch("relenv.create.arches", mocked_arches): with pytest.raises(CreateException): diff --git a/tests/test_relocate.py b/tests/test_relocate.py index 2b7aaa32..66f1668a 100644 --- a/tests/test_relocate.py +++ b/tests/test_relocate.py @@ -226,9 +226,9 @@ def test_handle_elf(tmp_path): ldd_ret = """ linux-vdso.so.1 => linux-vdso.so.1 (0x0123456789) - libcrypt.so.2 => {libcrypt} (0x0123456789) - libm.so.6 => /usr/lib/libm.so.6 (0x0123456789) - libc.so.6 => /usr/lib/libc.so.6 (0x0123456789) + libcrypt.so.2 => {libcrypt} (0x0123456789) + libm.so.6 => /usr/lib/libm.so.6 (0x0123456789) + libc.so.6 => /usr/lib/libc.so.6 (0x0123456789) """.format( libcrypt=libcrypt ).encode() @@ -254,10 +254,10 @@ def test_handle_elf_rpath_only(tmp_path): ldd_ret = """ linux-vdso.so.1 => linux-vdso.so.1 (0x0123456789) - libcrypt.so.2 => {libcrypt} (0x0123456789) - fake.so.2 => {fake} (0x0123456789) - libm.so.6 => /usr/lib/libm.so.6 (0x0123456789) - libc.so.6 => /usr/lib/libc.so.6 (0x0123456789) + libcrypt.so.2 => {libcrypt} (0x0123456789) + fake.so.2 => {fake} (0x0123456789) + libm.so.6 => /usr/lib/libm.so.6 (0x0123456789) + libc.so.6 => /usr/lib/libc.so.6 (0x0123456789) """.format( libcrypt=libcrypt, fake=fake ).encode() diff --git a/tests/test_verify_build.py b/tests/test_verify_build.py index dc1ff5a3..9b96d5d4 100644 --- a/tests/test_verify_build.py +++ b/tests/test_verify_build.py @@ -1,7 +1,7 @@ # Copyright 2022 VMware, Inc. # SPDX-License-Identifier: Apache-2 """ -Verify relenv builds +Verify relenv builds. """ import os import pathlib @@ -66,7 +66,7 @@ def test_directories(build): @pytest.mark.skip_unless_on_windows -def test_imports(pyexec): +def test_imports_windows(pyexec): modules = [ "asyncio", "binascii", @@ -138,7 +138,7 @@ def test_pip_install_salt_w_static_requirements(pipexec, build): p = subprocess.run(["git", "clone", "https://github.com/saltstack/salt.git"]) p = subprocess.run([str(pipexec), "install", "./salt", "--no-cache"], env=env) - assert p.returncode == 0, f"Failed to pip install ./salt" + assert p.returncode == 0, "Failed to pip install ./salt" names = ["salt", "salt-call", "salt-master", "salt-minion"] if sys.platform == "win32": @@ -209,7 +209,7 @@ def test_nox_virtualenvs(pipexec, build, tmp_path): nox_contents = textwrap.dedent( """ import nox - + @nox.session() def {}(session): session.install("nox")