diff --git a/backend/scripts/update_licenses.py b/backend/scripts/update_licenses.py index 4b252d7ba..a7820b43f 100644 --- a/backend/scripts/update_licenses.py +++ b/backend/scripts/update_licenses.py @@ -16,7 +16,7 @@ def download_data(url): try: response = httpx.get(url) response.raise_for_status() - except Exception: + except Exception: # noqa: BLE001 time.sleep(1) continue else: diff --git a/backend/src/hatchling/bridge/app.py b/backend/src/hatchling/bridge/app.py index d5fa1d4c7..151993448 100644 --- a/backend/src/hatchling/bridge/app.py +++ b/backend/src/hatchling/bridge/app.py @@ -14,31 +14,40 @@ def __init__(self) -> None: def verbosity(self) -> int: return self.__verbosity - def display(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display(*args: Any, **kwargs: Any) -> None: send_app_command('display', *args, **kwargs) - def display_info(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_info(*args: Any, **kwargs: Any) -> None: send_app_command('display_info', *args, **kwargs) - def display_waiting(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_waiting(*args: Any, **kwargs: Any) -> None: send_app_command('display_waiting', *args, **kwargs) - def display_success(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_success(*args: Any, **kwargs: Any) -> None: send_app_command('display_success', *args, **kwargs) - def display_warning(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_warning(*args: Any, **kwargs: Any) -> None: send_app_command('display_warning', *args, **kwargs) - def display_error(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_error(*args: Any, **kwargs: Any) -> None: send_app_command('display_error', *args, **kwargs) - def display_debug(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_debug(*args: Any, **kwargs: Any) -> None: send_app_command('display_debug', *args, **kwargs) - def display_mini_header(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def display_mini_header(*args: Any, **kwargs: Any) -> None: send_app_command('display_mini_header', *args, **kwargs) - def abort(self, *args: Any, **kwargs: Any) -> None: + @staticmethod + def abort(*args: Any, **kwargs: Any) -> None: send_app_command('abort', *args, **kwargs) sys.exit(kwargs.get('code', 1)) @@ -65,7 +74,8 @@ def verbosity(self) -> int: """ return self.__verbosity - def display(self, message: str = '', **kwargs: Any) -> None: # noqa: ARG002 + @staticmethod + def display(message: str = '', **kwargs: Any) -> None: # noqa: ARG004 # Do not document print(message) @@ -112,7 +122,8 @@ def display_debug(self, message: str = '', level: int = 1, **kwargs: Any) -> Non if not 1 <= level <= 3: # noqa: PLR2004 error_message = 'Debug output can only have verbosity levels between 1 and 3 (inclusive)' raise ValueError(error_message) - elif self.__verbosity >= level: + + if self.__verbosity >= level: print(message) def display_mini_header(self, message: str = '', **kwargs: Any) -> None: # noqa: ARG002 diff --git a/backend/src/hatchling/build.py b/backend/src/hatchling/build.py index ecd829f38..97f948e2f 100644 --- a/backend/src/hatchling/build.py +++ b/backend/src/hatchling/build.py @@ -11,7 +11,7 @@ 'get_requires_for_build_sdist', 'get_requires_for_build_wheel', ] -__all__.append('__all__') +__all__ += ['__all__'] def get_requires_for_build_sdist(config_settings: dict[str, Any] | None = None) -> list[str]: # noqa: ARG001 @@ -95,8 +95,7 @@ def build_editable( # See: https://github.com/pypa/pip/blob/22.2.2/src/pip/_internal/operations/build/build_tracker.py#L41-L51 # Example use case: https://github.com/pypa/hatch/issues/532 if 'PIP_BUILD_TRACKER' not in os.environ: - __all__.append('prepare_metadata_for_build_editable') - __all__.append('prepare_metadata_for_build_wheel') + __all__ += ['prepare_metadata_for_build_editable', 'prepare_metadata_for_build_wheel'] def prepare_metadata_for_build_wheel( metadata_directory: str, diff --git a/backend/src/hatchling/builders/app.py b/backend/src/hatchling/builders/app.py index a73c6ad05..85fe5de87 100644 --- a/backend/src/hatchling/builders/app.py +++ b/backend/src/hatchling/builders/app.py @@ -34,7 +34,8 @@ def scripts(self) -> list[str]: f'Script #{i} of field `tool.hatch.build.targets.{self.plugin_name}.scripts` must be a string' ) raise TypeError(message) - elif script not in known_scripts: + + if script not in known_scripts: message = f'Unknown script in field `tool.hatch.build.targets.{self.plugin_name}.scripts`: {script}' raise ValueError(message) @@ -88,11 +89,11 @@ class AppBuilder(BuilderInterface): def get_version_api(self) -> dict[str, Callable]: return {'bootstrap': self.build_bootstrap} - def get_default_versions(self) -> list[str]: + def get_default_versions(self) -> list[str]: # noqa: PLR6301 return ['bootstrap'] def clean( - self, + self, # noqa: PLR6301 directory: str, versions: list[str], # noqa: ARG002 ) -> None: @@ -188,7 +189,7 @@ def cargo_build(self, *args: Any, **kwargs: Any) -> None: kwargs['stdout'] = subprocess.PIPE kwargs['stderr'] = subprocess.STDOUT - process = subprocess.run(*args, **kwargs) + process = subprocess.run(*args, **kwargs) # noqa: PLW1510 if process.returncode: message = f'Compilation of failed (code {process.returncode})' if not self.app.verbosity: diff --git a/backend/src/hatchling/builders/config.py b/backend/src/hatchling/builders/config.py index 21e213af5..e3c03cc36 100644 --- a/backend/src/hatchling/builders/config.py +++ b/backend/src/hatchling/builders/config.py @@ -155,16 +155,16 @@ def include_spec(self) -> pathspec.GitIgnoreSpec | None: if not isinstance(include_pattern, str): message = f'Pattern #{i} in field `{include_location}` must be a string' raise TypeError(message) - elif not include_pattern: + + if not include_pattern: message = f'Pattern #{i} in field `{include_location}` cannot be an empty string' raise ValueError(message) all_include_patterns.append(include_pattern) - for relative_path in self.packages: - # Matching only at the root requires a forward slash, back slashes do not work. As such, - # normalize to forward slashes for consistency. - all_include_patterns.append(f"/{relative_path.replace(os.sep, '/')}/") + # Matching only at the root requires a forward slash, back slashes do not work. As such, + # normalize to forward slashes for consistency. + all_include_patterns.extend(f"/{relative_path.replace(os.sep, '/')}/" for relative_path in self.packages) if all_include_patterns: self.__include_spec = pathspec.GitIgnoreSpec.from_lines(all_include_patterns) @@ -194,7 +194,8 @@ def exclude_spec(self) -> pathspec.GitIgnoreSpec | None: if not isinstance(exclude_pattern, str): message = f'Pattern #{i} in field `{exclude_location}` must be a string' raise TypeError(message) - elif not exclude_pattern: + + if not exclude_pattern: message = f'Pattern #{i} in field `{exclude_location}` cannot be an empty string' raise ValueError(message) @@ -231,7 +232,8 @@ def artifact_spec(self) -> pathspec.GitIgnoreSpec | None: if not isinstance(artifact_pattern, str): message = f'Pattern #{i} in field `{artifact_location}` must be a string' raise TypeError(message) - elif not artifact_pattern: + + if not artifact_pattern: message = f'Pattern #{i} in field `{artifact_location}` cannot be an empty string' raise ValueError(message) @@ -381,15 +383,16 @@ def require_runtime_features(self) -> list[str]: raise TypeError(message) all_features: dict[str, None] = {} - for i, feature in enumerate(require_runtime_features, 1): - if not isinstance(feature, str): + for i, raw_feature in enumerate(require_runtime_features, 1): + if not isinstance(raw_feature, str): message = f'Feature #{i} of field `{features_location}` must be a string' raise TypeError(message) - elif not feature: + + if not raw_feature: message = f'Feature #{i} of field `{features_location}` cannot be an empty string' raise ValueError(message) - feature = normalize_project_name(feature) + feature = normalize_project_name(raw_feature) if feature not in self.builder.metadata.core.optional_dependencies: message = ( f'Feature `{feature}` of field `{features_location}` is not defined in ' @@ -470,7 +473,8 @@ def dev_mode_dirs(self) -> list[str]: if not isinstance(dev_mode_dir, str): message = f'Directory #{i} in field `{dev_mode_dirs_location}` must be a string' raise TypeError(message) - elif not dev_mode_dir: + + if not dev_mode_dir: message = f'Directory #{i} in field `{dev_mode_dirs_location}` cannot be an empty string' raise ValueError(message) @@ -515,7 +519,8 @@ def versions(self) -> list[str]: f'Version #{i} in field `tool.hatch.build.targets.{self.plugin_name}.versions` must be a string' ) raise TypeError(message) - elif not version: + + if not version: message = ( f'Version #{i} in field `tool.hatch.build.targets.{self.plugin_name}.versions` ' f'cannot be an empty string' @@ -581,7 +586,8 @@ def dependencies(self) -> list[str]: if not isinstance(hook_require_runtime_dependencies, bool): message = f'Option `require-runtime-dependencies` of build hook `{hook_name}` must be a boolean' raise TypeError(message) - elif hook_require_runtime_dependencies: + + if hook_require_runtime_dependencies: require_runtime_dependencies = True hook_require_runtime_features = config.get('require-runtime-features', []) @@ -589,21 +595,22 @@ def dependencies(self) -> list[str]: message = f'Option `require-runtime-features` of build hook `{hook_name}` must be an array' raise TypeError(message) - for i, feature in enumerate(hook_require_runtime_features, 1): - if not isinstance(feature, str): + for i, raw_feature in enumerate(hook_require_runtime_features, 1): + if not isinstance(raw_feature, str): message = ( f'Feature #{i} of option `require-runtime-features` of build hook `{hook_name}` ' f'must be a string' ) raise TypeError(message) - elif not feature: + + if not raw_feature: message = ( f'Feature #{i} of option `require-runtime-features` of build hook `{hook_name}` ' f'cannot be an empty string' ) raise ValueError(message) - feature = normalize_project_name(feature) + feature = normalize_project_name(raw_feature) if feature not in self.builder.metadata.core.optional_dependencies: message = ( f'Feature `{feature}` of option `require-runtime-features` of build hook `{hook_name}` ' @@ -658,7 +665,8 @@ def sources(self) -> dict[str, str]: if not isinstance(source, str): message = f'Source #{i} in field `{sources_location}` must be a string' raise TypeError(message) - elif not source: + + if not source: message = f'Source #{i} in field `{sources_location}` cannot be an empty string' raise ValueError(message) @@ -668,7 +676,8 @@ def sources(self) -> dict[str, str]: if not source: message = f'Source #{i} in field `{sources_location}` cannot be an empty string' raise ValueError(message) - elif not isinstance(path, str): + + if not isinstance(path, str): message = f'Path for source `{source}` in field `{sources_location}` must be a string' raise TypeError(message) @@ -711,7 +720,8 @@ def packages(self) -> list[str]: if not isinstance(package, str): message = f'Package #{i} in field `{package_location}` must be a string' raise TypeError(message) - elif not package: + + if not package: message = f'Package #{i} in field `{package_location}` cannot be an empty string' raise ValueError(message) @@ -738,10 +748,12 @@ def force_include(self) -> dict[str, str]: if not source: message = f'Source #{i} in field `{force_include_location}` cannot be an empty string' raise ValueError(message) - elif not isinstance(relative_path, str): + + if not isinstance(relative_path, str): message = f'Path for source `{source}` in field `{force_include_location}` must be a string' raise TypeError(message) - elif not relative_path: + + if not relative_path: message = ( f'Path for source `{source}` in field `{force_include_location}` cannot be an empty string' ) @@ -777,7 +789,8 @@ def only_include(self) -> dict[str, str]: if not normalized_path or normalized_path.startswith(('~', '..')): message = f'Path #{i} in field `{only_include_location}` must be relative: {relative_path}' raise ValueError(message) - elif normalized_path in inclusion_map: + + if normalized_path in inclusion_map: message = f'Duplicate path in field `{only_include_location}`: {normalized_path}' raise ValueError(message) @@ -829,10 +842,12 @@ def load_vcs_exclusion_patterns(self) -> list[str]: if exact_line == 'syntax: glob': glob_mode = True continue - elif exact_line.startswith('syntax: '): + + if exact_line.startswith('syntax: '): glob_mode = False continue - elif glob_mode: + + if glob_mode: patterns.append(line) return patterns @@ -843,19 +858,19 @@ def normalize_build_directory(self, build_directory: str) -> str: return os.path.normpath(build_directory) - def default_include(self) -> list: + def default_include(self) -> list: # noqa: PLR6301 return [] - def default_exclude(self) -> list: + def default_exclude(self) -> list: # noqa: PLR6301 return [] - def default_packages(self) -> list: + def default_packages(self) -> list: # noqa: PLR6301 return [] - def default_only_include(self) -> list: + def default_only_include(self) -> list: # noqa: PLR6301 return [] - def default_global_exclude(self) -> list[str]: + def default_global_exclude(self) -> list[str]: # noqa: PLR6301 patterns = ['*.py[cdo]', f'/{DEFAULT_BUILD_DIRECTORY}'] patterns.sort() return patterns @@ -897,8 +912,8 @@ def set_build_data(self, build_data: dict[str, Any]) -> Generator: def env_var_enabled(env_var: str, *, default: bool = False) -> bool: if env_var in os.environ: return os.environ[env_var] in ('1', 'true') - else: - return default + + return default BuilderConfigBound = TypeVar('BuilderConfigBound', bound=BuilderConfig) diff --git a/backend/src/hatchling/builders/custom.py b/backend/src/hatchling/builders/custom.py index ebbad6f40..29c80317e 100644 --- a/backend/src/hatchling/builders/custom.py +++ b/backend/src/hatchling/builders/custom.py @@ -35,7 +35,8 @@ def __new__( # type: ignore if not isinstance(build_script, str): message = f'Option `path` for builder `{cls.PLUGIN_NAME}` must be a string' raise TypeError(message) - elif not build_script: + + if not build_script: message = f'Option `path` for builder `{cls.PLUGIN_NAME}` must not be empty if defined' raise ValueError(message) diff --git a/backend/src/hatchling/builders/hooks/custom.py b/backend/src/hatchling/builders/hooks/custom.py index 74a38c5b4..1af099308 100644 --- a/backend/src/hatchling/builders/hooks/custom.py +++ b/backend/src/hatchling/builders/hooks/custom.py @@ -22,7 +22,8 @@ def __new__( # type: ignore if not isinstance(build_script, str): message = f'Option `path` for build hook `{cls.PLUGIN_NAME}` must be a string' raise TypeError(message) - elif not build_script: + + if not build_script: message = f'Option `path` for build hook `{cls.PLUGIN_NAME}` must not be empty if defined' raise ValueError(message) diff --git a/backend/src/hatchling/builders/hooks/version.py b/backend/src/hatchling/builders/hooks/version.py index 14d48e6fb..20dfb8a7d 100644 --- a/backend/src/hatchling/builders/hooks/version.py +++ b/backend/src/hatchling/builders/hooks/version.py @@ -23,7 +23,8 @@ def config_path(self) -> str: if not isinstance(path, str): message = f'Option `path` for build hook `{self.PLUGIN_NAME}` must be a string' raise TypeError(message) - elif not path: + + if not path: message = f'Option `path` for build hook `{self.PLUGIN_NAME}` is required' raise ValueError(message) diff --git a/backend/src/hatchling/builders/plugin/interface.py b/backend/src/hatchling/builders/plugin/interface.py index 8558a2401..08d152283 100644 --- a/backend/src/hatchling/builders/plugin/interface.py +++ b/backend/src/hatchling/builders/plugin/interface.py @@ -388,13 +388,13 @@ def get_default_versions(self) -> list[str]: """ return list(self.get_version_api()) - def get_default_build_data(self) -> dict[str, Any]: + def get_default_build_data(self) -> dict[str, Any]: # noqa: PLR6301 """ A mapping that can be modified by [build hooks](../build-hook/reference.md) to influence the behavior of builds. """ return {} - def set_build_data_defaults(self, build_data: dict[str, Any]) -> None: + def set_build_data_defaults(self, build_data: dict[str, Any]) -> None: # noqa: PLR6301 build_data.setdefault('artifacts', []) build_data.setdefault('force_include', {}) @@ -416,4 +416,4 @@ def normalize_file_name_component(file_name: str) -> str: """ https://peps.python.org/pep-0427/#escaping-and-unicode """ - return re.sub(r'[^\w\d.]+', '_', file_name, re.UNICODE) + return re.sub(r'[^\w\d.]+', '_', file_name, flags=re.UNICODE) diff --git a/backend/src/hatchling/builders/sdist.py b/backend/src/hatchling/builders/sdist.py index bef8f5571..b9b0f73d1 100644 --- a/backend/src/hatchling/builders/sdist.py +++ b/backend/src/hatchling/builders/sdist.py @@ -74,7 +74,7 @@ def __getattr__(self, name: str) -> Any: setattr(self, name, attr) return attr - def __enter__(self) -> SdistArchive: + def __enter__(self) -> SdistArchive: # noqa: PYI034 return self def __exit__( @@ -150,11 +150,11 @@ class SdistBuilder(BuilderInterface): def get_version_api(self) -> dict[str, Callable]: return {'standard': self.build_standard} - def get_default_versions(self) -> list[str]: + def get_default_versions(self) -> list[str]: # noqa: PLR6301 return ['standard'] def clean( - self, + self, # noqa: PLR6301 directory: str, versions: list[str], # noqa: ARG002 ) -> None: @@ -249,8 +249,8 @@ def construct_setup_py_file(self, packages: list[str], extra_dependencies: tuple if dependencies: contents += ' install_requires=[\n' - for specifier in dependencies: - specifier = specifier.replace("'", '"') + for raw_specifier in dependencies: + specifier = raw_specifier.replace("'", '"') contents += f' {specifier!r},\n' contents += ' ],\n' @@ -264,8 +264,8 @@ def construct_setup_py_file(self, packages: list[str], extra_dependencies: tuple contents += f' {option!r}: [\n' - for specifier in specifiers: - specifier = specifier.replace("'", '"') + for raw_specifier in specifiers: + specifier = raw_specifier.replace("'", '"') contents += f' {specifier!r},\n' contents += ' ],\n' @@ -342,8 +342,8 @@ def get_default_build_data(self) -> dict[str, Any]: license_files = self.metadata.core.license_files if license_files: for license_file in license_files: - license_file = normalize_relative_path(license_file) - force_include[os.path.join(self.root, license_file)] = license_file + relative_path = normalize_relative_path(license_file) + force_include[os.path.join(self.root, relative_path)] = relative_path return build_data diff --git a/backend/src/hatchling/builders/utils.py b/backend/src/hatchling/builders/utils.py index d20b0e05c..598fe14f8 100644 --- a/backend/src/hatchling/builders/utils.py +++ b/backend/src/hatchling/builders/utils.py @@ -56,8 +56,8 @@ def normalize_relative_directory(path: str) -> str: def normalize_inclusion_map(inclusion_map: dict[str, str], root: str) -> dict[str, str]: normalized_inclusion_map = {} - for source, relative_path in inclusion_map.items(): - source = os.path.expanduser(os.path.normpath(source)) + for raw_source, relative_path in inclusion_map.items(): + source = os.path.expanduser(os.path.normpath(raw_source)) if not os.path.isabs(source): source = os.path.abspath(os.path.join(root, source)) diff --git a/backend/src/hatchling/builders/wheel.py b/backend/src/hatchling/builders/wheel.py index 9f8973265..9577eafaf 100644 --- a/backend/src/hatchling/builders/wheel.py +++ b/backend/src/hatchling/builders/wheel.py @@ -46,7 +46,7 @@ def write(self, record: Iterable[Any]) -> None: def construct(self) -> str: return self.__file_obj.getvalue() - def __enter__(self) -> RecordFile: + def __enter__(self) -> RecordFile: # noqa: PYI034 return self def __exit__( @@ -139,7 +139,7 @@ def write_file(self, relative_path: str, contents: str | bytes) -> tuple[str, st return relative_path, f'sha256={hash_digest}', str(len(contents)) - def __enter__(self) -> WheelArchive: + def __enter__(self) -> WheelArchive: # noqa: PYI034 return self def __exit__( @@ -180,21 +180,23 @@ def set_default_file_selection(self) -> None: if os.path.isfile(os.path.join(self.root, project_name, '__init__.py')): self.__packages.append(project_name) break - elif os.path.isfile(os.path.join(self.root, 'src', project_name, '__init__.py')): + + if os.path.isfile(os.path.join(self.root, 'src', project_name, '__init__.py')): self.__packages.append(f'src/{project_name}') break - elif os.path.isfile(os.path.join(self.root, f'{project_name}.py')): + + if os.path.isfile(os.path.join(self.root, f'{project_name}.py')): self.__only_include.append(f'{project_name}.py') break - else: - from glob import glob - possible_namespace_packages = glob(os.path.join(self.root, '*', project_name, '__init__.py')) - if len(possible_namespace_packages) == 1: - relative_path = os.path.relpath(possible_namespace_packages[0], self.root) - namespace = relative_path.split(os.sep)[0] - self.__packages.append(namespace) - break + from glob import glob + + possible_namespace_packages = glob(os.path.join(self.root, '*', project_name, '__init__.py')) + if len(possible_namespace_packages) == 1: + relative_path = os.path.relpath(possible_namespace_packages[0], self.root) + namespace = relative_path.split(os.sep)[0] + self.__packages.append(namespace) + break else: self.__include.append('*.py') self.__exclude.append('test*') @@ -259,13 +261,15 @@ def shared_data(self) -> dict[str, str]: f'cannot be an empty string' ) raise ValueError(message) - elif not isinstance(relative_path, str): + + if not isinstance(relative_path, str): message = ( f'Path for source `{source}` in field ' f'`tool.hatch.build.targets.{self.plugin_name}.shared-data` must be a string' ) raise TypeError(message) - elif not relative_path: + + if not relative_path: message = ( f'Path for source `{source}` in field ' f'`tool.hatch.build.targets.{self.plugin_name}.shared-data` cannot be an empty string' @@ -291,13 +295,15 @@ def extra_metadata(self) -> dict[str, str]: f'cannot be an empty string' ) raise ValueError(message) - elif not isinstance(relative_path, str): + + if not isinstance(relative_path, str): message = ( f'Path for source `{source}` in field ' f'`tool.hatch.build.targets.{self.plugin_name}.extra-metadata` must be a string' ) raise TypeError(message) - elif not relative_path: + + if not relative_path: message = ( f'Path for source `{source}` in field ' f'`tool.hatch.build.targets.{self.plugin_name}.extra-metadata` cannot be an empty string' @@ -349,11 +355,11 @@ class WheelBuilder(BuilderInterface): def get_version_api(self) -> dict[str, Callable]: return {'standard': self.build_standard, 'editable': self.build_editable} - def get_default_versions(self) -> list[str]: + def get_default_versions(self) -> list[str]: # noqa: PLR6301 return ['standard'] def clean( - self, + self, # noqa: PLR6301 directory: str, versions: list[str], # noqa: ARG002 ) -> None: @@ -388,8 +394,8 @@ def build_standard(self, directory: str, **build_data: Any) -> str: def build_editable(self, directory: str, **build_data: Any) -> str: if self.config.dev_mode_dirs: return self.build_editable_explicit(directory, **build_data) - else: - return self.build_editable_detection(directory, **build_data) + + return self.build_editable_detection(directory, **build_data) def build_editable_detection(self, directory: str, **build_data: Any) -> str: from editables import EditableProject @@ -441,7 +447,8 @@ def build_editable_detection(self, directory: str, **build_data: Any) -> str: for relative_path in exposed_packages.values(): editable_project.add_to_path(os.path.dirname(relative_path)) - for filename, content in sorted(editable_project.files()): + for raw_filename, content in sorted(editable_project.files()): + filename = raw_filename if filename.endswith('.pth') and not filename.startswith('_'): filename = f'_{filename}' @@ -453,7 +460,8 @@ def build_editable_detection(self, directory: str, **build_data: Any) -> str: records.write(record) extra_dependencies = list(build_data['dependencies']) - for dependency in editable_project.dependencies(): + for raw_dependency in editable_project.dependencies(): + dependency = raw_dependency if dependency == 'editables': dependency += f'~={EDITABLES_MINIMUM_VERSION}' else: # no cov @@ -537,7 +545,8 @@ def write_metadata( # extra_metadata/ - write last self.add_extra_metadata(archive, records, build_data) - def write_archive_metadata(self, archive: WheelArchive, records: RecordFile, build_data: dict[str, Any]) -> None: + @staticmethod + def write_archive_metadata(archive: WheelArchive, records: RecordFile, build_data: dict[str, Any]) -> None: from packaging.tags import parse_tag metadata = f"""\ @@ -646,7 +655,7 @@ def get_best_matching_tag(self) -> str: return '-'.join(tag_parts) - def get_default_build_data(self) -> dict[str, Any]: + def get_default_build_data(self) -> dict[str, Any]: # noqa: PLR6301 return { 'infer_tag': False, 'pure_python': True, diff --git a/backend/src/hatchling/cli/dep/__init__.py b/backend/src/hatchling/cli/dep/__init__.py index 234c846f6..358f3d448 100644 --- a/backend/src/hatchling/cli/dep/__init__.py +++ b/backend/src/hatchling/cli/dep/__init__.py @@ -23,14 +23,14 @@ def synced_impl(*, dependencies: list[str], python: str) -> None: sys.exit(0 if dependencies_in_sync(list(map(Requirement, dependencies)), sys_path) else 1) -def synced_command(subparsers: argparse._SubParsersAction, defaults: Any) -> None: +def synced_command(subparsers: argparse._SubParsersAction, defaults: Any) -> None: # noqa: SLF001 parser = subparsers.add_parser('synced') parser.add_argument('dependencies', nargs='+') parser.add_argument('-p', '--python', dest='python', **defaults) parser.set_defaults(func=synced_impl) -def dep_command(subparsers: argparse._SubParsersAction, defaults: Any) -> None: +def dep_command(subparsers: argparse._SubParsersAction, defaults: Any) -> None: # noqa: SLF001 parser = subparsers.add_parser('dep') subparsers = parser.add_subparsers() diff --git a/backend/src/hatchling/cli/metadata/__init__.py b/backend/src/hatchling/cli/metadata/__init__.py index 9c0ec7767..cc4f152b7 100644 --- a/backend/src/hatchling/cli/metadata/__init__.py +++ b/backend/src/hatchling/cli/metadata/__init__.py @@ -43,7 +43,7 @@ def metadata_impl(*, called_by_app: bool, field: str, compact: bool) -> None: def metadata_command( - subparsers: argparse._SubParsersAction, + subparsers: argparse._SubParsersAction, # noqa: SLF001 defaults: Any, # noqa: ARG001 ) -> None: parser = subparsers.add_parser('metadata') diff --git a/backend/src/hatchling/cli/version/__init__.py b/backend/src/hatchling/cli/version/__init__.py index 723320a88..4e49dbb64 100644 --- a/backend/src/hatchling/cli/version/__init__.py +++ b/backend/src/hatchling/cli/version/__init__.py @@ -40,7 +40,7 @@ def version_impl(*, called_by_app: bool, desired_version: str) -> None: app.display_info(f'New: {updated_version}') -def version_command(subparsers: argparse._SubParsersAction, defaults: Any) -> None: +def version_command(subparsers: argparse._SubParsersAction, defaults: Any) -> None: # noqa: SLF001 parser = subparsers.add_parser('version') parser.add_argument('desired_version', default='', nargs='?', **defaults) parser.add_argument('--app', dest='called_by_app', action='store_true', help=argparse.SUPPRESS) diff --git a/backend/src/hatchling/dep/core.py b/backend/src/hatchling/dep/core.py index b00f615bb..0eef5e31c 100644 --- a/backend/src/hatchling/dep/core.py +++ b/backend/src/hatchling/dep/core.py @@ -20,9 +20,10 @@ def __getitem__(self, item: str) -> Distribution | None: possible_distribution = self._distributions.get(item) if possible_distribution is not None: return possible_distribution + # Be safe even though the code as-is will never reach this since # the first unknown distribution will fail fast - elif self._search_exhausted: # no cov + if self._search_exhausted: # no cov return None for distribution in self._resolver: @@ -76,8 +77,9 @@ def dependency_in_sync( if requirement.specifier and not requirement.specifier.contains(distribution.version): return False + # TODO: handle https://discuss.python.org/t/11938 - elif requirement.url: + if requirement.url: direct_url_file = distribution.read_text('direct_url.json') if direct_url_file is not None: import json @@ -96,7 +98,8 @@ def dependency_in_sync( requested_revision and requirement.url == f'{vcs}+{url}@{requested_revision}#{commit_id}' ) or requirement.url == f'{vcs}+{url}@{commit_id}': return True - elif requirement.url == f'{vcs}+{url}' or requirement.url == f'{vcs}+{url}@{requested_revision}': + + if requirement.url in (f'{vcs}+{url}', f'{vcs}+{url}@{requested_revision}'): import subprocess if vcs == 'git': @@ -106,13 +109,13 @@ def dependency_in_sync( # TODO: add elifs for hg, svn, and bzr https://github.com/pypa/hatch/issues/760 else: return False - result = subprocess.run(vcs_cmd, capture_output=True, text=True) + result = subprocess.run(vcs_cmd, capture_output=True, text=True) # noqa: PLW1510 if result.returncode: return False latest_commit_id, *_ = result.stdout.split() return commit_id == latest_commit_id - else: - return False + + return False return True diff --git a/backend/src/hatchling/licenses/parse.py b/backend/src/hatchling/licenses/parse.py index 251eeb416..4698b0aad 100644 --- a/backend/src/hatchling/licenses/parse.py +++ b/backend/src/hatchling/licenses/parse.py @@ -51,8 +51,8 @@ def normalize_license_expression(raw_license_expression: str) -> str: python_expression = ' '.join(python_tokens) try: - result = eval(python_expression) - except Exception: + result = eval(python_expression) # noqa: PGH001, S307 + except Exception: # noqa: BLE001 result = True if result is not False: @@ -74,21 +74,20 @@ def normalize_license_expression(raw_license_expression: str) -> str: normalized_tokens.append(cast(str, EXCEPTIONS[token]['id'])) else: if token.endswith('+'): - token = token[:-1] + final_token = token[:-1] suffix = '+' else: + final_token = token suffix = '' - if token not in valid_licenses: - message = f'unknown license: {token}' + if final_token not in valid_licenses: + message = f'unknown license: {final_token}' raise ValueError(message) - normalized_tokens.append(cast(str, valid_licenses[token]['id']) + suffix) + normalized_tokens.append(cast(str, valid_licenses[final_token]['id']) + suffix) # Construct the normalized expression normalized_expression = ' '.join(normalized_tokens) # Fix internal padding for parentheses - normalized_expression = normalized_expression.replace('( ', '(').replace(' )', ')') - - return normalized_expression + return normalized_expression.replace('( ', '(').replace(' )', ')') diff --git a/backend/src/hatchling/metadata/core.py b/backend/src/hatchling/metadata/core.py index 7971a6c5f..d7bed8c4c 100644 --- a/backend/src/hatchling/metadata/core.py +++ b/backend/src/hatchling/metadata/core.py @@ -225,7 +225,7 @@ def _get_version(self, core_metadata: CoreMetadata | None = None) -> str: if version is None: version = self.hatch.version.cached source = f'source `{self.hatch.version.source_name}`' - core_metadata._version_set = True + core_metadata._version_set = True # noqa: SLF001 else: source = 'field `project.version`' @@ -385,7 +385,8 @@ def raw_name(self) -> str: if not raw_name: message = 'Missing required field `project.name`' raise ValueError(message) - elif not isinstance(raw_name, str): + + if not isinstance(raw_name, str): message = 'Field `project.name` must be a string' raise TypeError(message) @@ -517,10 +518,12 @@ def readme(self) -> str: if content_type is None: message = 'Field `content-type` is required in the `project.readme` table' raise ValueError(message) - elif not isinstance(content_type, str): + + if not isinstance(content_type, str): message = 'Field `content-type` in the `project.readme` table must be a string' raise TypeError(message) - elif content_type not in ('text/markdown', 'text/x-rst', 'text/plain'): + + if content_type not in ('text/markdown', 'text/x-rst', 'text/plain'): message = ( 'Field `content-type` in the `project.readme` table must be one of the following: ' 'text/markdown, text/x-rst, text/plain' @@ -723,7 +726,8 @@ def license_files(self) -> list[str]: if not isinstance(data, dict): message = 'Field `project.license-files` must be a table' raise TypeError(message) - elif 'paths' in data and 'globs' in data: + + if 'paths' in data and 'globs' in data: message = 'Cannot specify both `paths` and `globs` in the `project.license-files` table' raise ValueError(message) @@ -759,9 +763,11 @@ def license_files(self) -> list[str]: raise TypeError(message) full_pattern = os.path.normpath(os.path.join(self.root, pattern)) - for path in glob(full_pattern): - if os.path.isfile(path): - license_files.append(os.path.relpath(path, self.root).replace('\\', '/')) + license_files.extend( + os.path.relpath(path, self.root).replace('\\', '/') + for path in glob(full_pattern) + if os.path.isfile(path) + ) else: message = 'Must specify either `paths` or `globs` in the `project.license-files` table if defined' raise ValueError(message) @@ -973,7 +979,8 @@ def classifiers(self) -> list[str]: if not isinstance(classifier, str): message = f'Classifier #{i} of field `project.classifiers` must be a string' raise TypeError(message) - elif not self.__classifier_is_private(classifier) and classifier not in known_classifiers: + + if not self.__classifier_is_private(classifier) and classifier not in known_classifiers: message = f'Unknown classifier in field `project.classifiers`: {classifier}' raise ValueError(message) @@ -1235,7 +1242,8 @@ def optional_dependencies_complex(self) -> dict[str, dict[str, Requirement]]: f'ASCII letters/digits.' ) raise ValueError(message) - elif not isinstance(dependencies, list): + + if not isinstance(dependencies, list): message = ( f'Dependencies for option `{option}` of field `project.optional-dependencies` must be an array' ) @@ -1310,7 +1318,8 @@ def dynamic(self) -> list[str]: if not isinstance(self._dynamic, list): message = 'Field `project.dynamic` must be an array' raise TypeError(message) - elif not all(isinstance(entry, str) for entry in self._dynamic): + + if not all(isinstance(entry, str) for entry in self._dynamic): message = 'Field `project.dynamic` must only contain strings' raise TypeError(message) @@ -1410,7 +1419,7 @@ def cached(self) -> str: if self._cached is None: try: self._cached = self.source.get_version_data()['version'] - except Exception as e: + except Exception as e: # noqa: BLE001 message = f'Error getting the version from source `{self.source.PLUGIN_NAME}`: {e}' raise type(e)(message) from None @@ -1423,7 +1432,8 @@ def source_name(self) -> str: if not source: message = 'The `source` option under the `tool.hatch.version` table must not be empty if defined' raise ValueError(message) - elif not isinstance(source, str): + + if not isinstance(source, str): message = 'Field `tool.hatch.version.source` must be a string' raise TypeError(message) @@ -1438,7 +1448,8 @@ def scheme_name(self) -> str: if not scheme: message = 'The `scheme` option under the `tool.hatch.version` table must not be empty if defined' raise ValueError(message) - elif not isinstance(scheme, str): + + if not isinstance(scheme, str): message = 'Field `tool.hatch.version.scheme` must be a string' raise TypeError(message) diff --git a/backend/src/hatchling/metadata/custom.py b/backend/src/hatchling/metadata/custom.py index 731ae28b8..148d14b95 100644 --- a/backend/src/hatchling/metadata/custom.py +++ b/backend/src/hatchling/metadata/custom.py @@ -22,7 +22,8 @@ def __new__( # type: ignore if not isinstance(build_script, str): message = f'Option `path` for metadata hook `{cls.PLUGIN_NAME}` must be a string' raise TypeError(message) - elif not build_script: + + if not build_script: message = f'Option `path` for metadata hook `{cls.PLUGIN_NAME}` must not be empty if defined' raise ValueError(message) diff --git a/backend/src/hatchling/metadata/plugin/interface.py b/backend/src/hatchling/metadata/plugin/interface.py index a4b0e076d..b6c8fdbf5 100644 --- a/backend/src/hatchling/metadata/plugin/interface.py +++ b/backend/src/hatchling/metadata/plugin/interface.py @@ -59,7 +59,7 @@ def update(self, metadata: dict) -> None: This updates the metadata mapping of the `project` table in-place. """ - def get_known_classifiers(self) -> list[str]: + def get_known_classifiers(self) -> list[str]: # noqa: PLR6301 """ This returns extra classifiers that should be considered valid in addition to the ones known to PyPI. """ diff --git a/backend/src/hatchling/ouroboros.py b/backend/src/hatchling/ouroboros.py index 37b4ed83d..b7b286d53 100644 --- a/backend/src/hatchling/ouroboros.py +++ b/backend/src/hatchling/ouroboros.py @@ -24,7 +24,7 @@ def read_dependencies() -> list[str]: def get_requires_for_build_sdist( # type: ignore[no-redef] - config_settings: dict[str, Any] | None = None # noqa: ARG001 + config_settings: dict[str, Any] | None = None, # noqa: ARG001 ) -> list[str]: """ https://peps.python.org/pep-0517/#get-requires-for-build-sdist @@ -33,7 +33,7 @@ def get_requires_for_build_sdist( # type: ignore[no-redef] def get_requires_for_build_wheel( # type: ignore[no-redef] - config_settings: dict[str, Any] | None = None # noqa: ARG001 + config_settings: dict[str, Any] | None = None, # noqa: ARG001 ) -> list[str]: """ https://peps.python.org/pep-0517/#get-requires-for-build-wheel @@ -42,7 +42,7 @@ def get_requires_for_build_wheel( # type: ignore[no-redef] def get_requires_for_build_editable( # type: ignore[no-redef] - config_settings: dict[str, Any] | None = None # noqa: ARG001 + config_settings: dict[str, Any] | None = None, # noqa: ARG001 ) -> list[str]: """ https://peps.python.org/pep-0660/#get-requires-for-build-editable diff --git a/backend/src/hatchling/plugin/manager.py b/backend/src/hatchling/plugin/manager.py index d0e4508fa..70773cccc 100644 --- a/backend/src/hatchling/plugin/manager.py +++ b/backend/src/hatchling/plugin/manager.py @@ -68,16 +68,17 @@ def collect(self, *, include_third_party: bool = True) -> dict: classes: dict[str, type] = {} - for registered_classes in self.registration_method(): - if not isinstance(registered_classes, list): - registered_classes = [registered_classes] - + for raw_registered_classes in self.registration_method(): + registered_classes = ( + raw_registered_classes if isinstance(raw_registered_classes, list) else [raw_registered_classes] + ) for registered_class in registered_classes: name = getattr(registered_class, self.identifier, None) if not name: # no cov message = f'Class `{registered_class.__name__}` does not have a {name} attribute.' raise ValueError(message) - elif name in classes: # no cov + + if name in classes: # no cov message = ( f'Class `{registered_class.__name__}` defines its name as `{name}` but ' f'that name is already used by `{classes[name].__name__}`.' diff --git a/backend/src/hatchling/plugin/utils.py b/backend/src/hatchling/plugin/utils.py index 1bef28097..2965f182b 100644 --- a/backend/src/hatchling/plugin/utils.py +++ b/backend/src/hatchling/plugin/utils.py @@ -37,11 +37,12 @@ def load_plugin_from_script(path: str, script_name: str, plugin_class: type[T], if not subclasses: message = f'Unable to find a subclass of `{plugin_class.__name__}` in `{script_name}`: {path}' raise ValueError(message) - elif len(subclasses) > 1: + + if len(subclasses) > 1: message = ( f'Multiple subclasses of `{plugin_class.__name__}` found in `{script_name}`, ' f'select one by defining a function named `{plugin_finder}`: {path}' ) raise ValueError(message) - else: - return subclasses[0] + + return subclasses[0] diff --git a/backend/src/hatchling/utils/context.py b/backend/src/hatchling/utils/context.py index 4ffee3661..b4f43134c 100644 --- a/backend/src/hatchling/utils/context.py +++ b/backend/src/hatchling/utils/context.py @@ -25,13 +25,15 @@ def get_formatters(self) -> MutableMapping: def format_path(cls, path: str, modifier: str) -> str: if not modifier: return os.path.normpath(path) - elif modifier == 'uri': + + if modifier == 'uri': return path_to_uri(path) - elif modifier == 'real': + + if modifier == 'real': return os.path.realpath(path) - else: - message = f'Unknown path modifier: {modifier}' - raise ValueError(message) + + message = f'Unknown path modifier: {modifier}' + raise ValueError(message) class DefaultContextFormatter(ContextFormatter): @@ -49,10 +51,10 @@ def get_formatters(self) -> MutableMapping: 'root': self.__format_root, } - def __format_directory_separator(self, value: str, data: str) -> str: # noqa: ARG002 + def __format_directory_separator(self, value: str, data: str) -> str: # noqa: ARG002, PLR6301 return os.sep - def __format_path_separator(self, value: str, data: str) -> str: # noqa: ARG002 + def __format_path_separator(self, value: str, data: str) -> str: # noqa: ARG002, PLR6301 return os.pathsep def __format_root(self, value: str, data: str) -> str: # noqa: ARG002 @@ -61,7 +63,7 @@ def __format_root(self, value: str, data: str) -> str: # noqa: ARG002 def __format_home(self, value: str, data: str) -> str: # noqa: ARG002 return self.format_path(os.path.expanduser('~'), data) - def __format_env(self, value: str, data: str) -> str: # noqa: ARG002 + def __format_env(self, value: str, data: str) -> str: # noqa: ARG002, PLR6301 if not data: message = 'The `env` context formatting field requires a modifier' raise ValueError(message) @@ -69,11 +71,12 @@ def __format_env(self, value: str, data: str) -> str: # noqa: ARG002 env_var, separator, default = data.partition(':') if env_var in os.environ: return os.environ[env_var] - elif not separator: + + if not separator: message = f'Nonexistent environment variable must set a default: {env_var}' raise ValueError(message) - else: - return default + + return default class Context: @@ -132,19 +135,19 @@ def get_value(self, key: int | str, args: Sequence[Any], kwargs: Mapping[str, An if key in self.__formatters: # Avoid hard look-up and rely on `None` to indicate that the field is undefined return kwargs.get(str(key)) - else: - try: - return super().get_value(key, args, kwargs) - except KeyError: - message = f'Unknown context field `{key}`' - raise ValueError(message) from None + + try: + return super().get_value(key, args, kwargs) + except KeyError: + message = f'Unknown context field `{key}`' + raise ValueError(message) from None def format_field(self, value: Any, format_spec: str) -> Any: formatter, _, data = format_spec.partition(':') if formatter in self.__formatters: return self.__formatters[formatter](value, data) - else: - return super().format_field(value, format_spec) + + return super().format_field(value, format_spec) def parse(self, format_string: str) -> Iterable: for literal_text, field_name, format_spec, conversion in super().parse(format_string): diff --git a/backend/src/hatchling/utils/fs.py b/backend/src/hatchling/utils/fs.py index 364b7fedd..70e5f21ed 100644 --- a/backend/src/hatchling/utils/fs.py +++ b/backend/src/hatchling/utils/fs.py @@ -19,5 +19,5 @@ def locate_file(root: str, file_name: str) -> str | None: def path_to_uri(path: str) -> str: if os.sep == '/': return f'file://{os.path.abspath(path)}' - else: - return f'file:///{os.path.abspath(path).replace(os.sep, "/")}' + + return f'file:///{os.path.abspath(path).replace(os.sep, "/")}' diff --git a/backend/src/hatchling/version/scheme/standard.py b/backend/src/hatchling/version/scheme/standard.py index 945555072..984b4152d 100644 --- a/backend/src/hatchling/version/scheme/standard.py +++ b/backend/src/hatchling/version/scheme/standard.py @@ -60,15 +60,15 @@ def update( if self.config.get('validate-bump', True) and next_version <= original: message = f'Version `{version}` is not higher than the original version `{original_version}`' raise ValueError(message) - else: - return str(next_version) + + return str(next_version) return str(original) def reset_version_parts(version: Version, **kwargs: Any) -> None: # https://github.com/pypa/packaging/blob/20.9/packaging/version.py#L301-L310 - internal_version = version._version + internal_version = version._version # noqa: SLF001 parts: dict[str, Any] = {'epoch': 0} ordered_part_names = ('release', 'pre', 'post', 'dev', 'local') @@ -82,13 +82,12 @@ def reset_version_parts(version: Version, **kwargs: Any) -> None: else: parts[part_name] = getattr(internal_version, part_name) - version._version = type(internal_version)(**parts) + version._version = type(internal_version)(**parts) # noqa: SLF001 def update_release(original_version: Version, new_release_parts: list[int]) -> tuple[int, ...]: # Retain release length - for _ in range(len(original_version.release) - len(new_release_parts)): - new_release_parts.append(0) + new_release_parts.extend(0 for _ in range(len(original_version.release) - len(new_release_parts))) return tuple(new_release_parts) diff --git a/backend/src/hatchling/version/source/code.py b/backend/src/hatchling/version/source/code.py index 1b6ae6f8b..9e99ab336 100644 --- a/backend/src/hatchling/version/source/code.py +++ b/backend/src/hatchling/version/source/code.py @@ -16,7 +16,8 @@ def get_version_data(self) -> dict: if not relative_path: message = 'option `path` must be specified' raise ValueError(message) - elif not isinstance(relative_path, str): + + if not isinstance(relative_path, str): message = 'option `path` must be a string' raise TypeError(message) @@ -54,10 +55,10 @@ def get_version_data(self) -> dict: sys.path[:] = old_search_paths # Execute the expression to determine the version - version = eval(expression, vars(module)) + version = eval(expression, vars(module)) # noqa: PGH001, S307 return {'version': version} - def set_version(self, version: str, version_data: dict) -> None: # noqa: ARG002 + def set_version(self, version: str, version_data: dict) -> None: # noqa: ARG002, PLR6301 message = 'Cannot rewrite loaded code' raise NotImplementedError(message) diff --git a/backend/src/hatchling/version/source/env.py b/backend/src/hatchling/version/source/env.py index 7466f8a6e..b46389437 100644 --- a/backend/src/hatchling/version/source/env.py +++ b/backend/src/hatchling/version/source/env.py @@ -13,7 +13,8 @@ def get_version_data(self) -> dict: if not variable: message = 'option `variable` must be specified' raise ValueError(message) - elif not isinstance(variable, str): + + if not isinstance(variable, str): message = 'option `variable` must be a string' raise TypeError(message) @@ -23,6 +24,6 @@ def get_version_data(self) -> dict: return {'version': os.environ[variable]} - def set_version(self, version: str, version_data: dict) -> None: # noqa: ARG002 + def set_version(self, version: str, version_data: dict) -> None: # noqa: ARG002, PLR6301 message = 'Cannot set environment variables' raise NotImplementedError(message) diff --git a/backend/src/hatchling/version/source/regex.py b/backend/src/hatchling/version/source/regex.py index 5e0d28c41..ff2d89542 100644 --- a/backend/src/hatchling/version/source/regex.py +++ b/backend/src/hatchling/version/source/regex.py @@ -10,7 +10,8 @@ def get_version_data(self) -> dict: if not relative_path: message = 'option `path` must be specified' raise ValueError(message) - elif not isinstance(relative_path, str): + + if not isinstance(relative_path, str): message = 'option `path` must be a string' raise TypeError(message) @@ -24,5 +25,5 @@ def get_version_data(self) -> dict: return {'version': version, 'version_file': version_file} - def set_version(self, version: str, version_data: dict) -> None: + def set_version(self, version: str, version_data: dict) -> None: # noqa: PLR6301 version_data['version_file'].set_version(version) diff --git a/backend/tests/downstream/integrate.py b/backend/tests/downstream/integrate.py index d007c8396..544e64a94 100644 --- a/backend/tests/downstream/integrate.py +++ b/backend/tests/downstream/integrate.py @@ -23,7 +23,7 @@ def handle_remove_readonly(func, path, exc): # no cov # PermissionError: [WinError 5] Access is denied: '...\\.git\\...' if func in (os.rmdir, os.remove, os.unlink) and exc[1].errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # noqa: S103 + os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) func(path) else: raise @@ -82,26 +82,28 @@ def get_venv_exe_dir(venv_dir): exe_dir = os.path.join(venv_dir, 'Scripts' if ON_WINDOWS else 'bin') if os.path.isdir(exe_dir): return exe_dir + # PyPy - elif ON_WINDOWS: + if ON_WINDOWS: exe_dir = os.path.join(venv_dir, 'bin') if os.path.isdir(exe_dir): return exe_dir - else: - message = f'Unable to locate executables directory within: {venv_dir}' - raise OSError(message) + + message = f'Unable to locate executables directory within: {venv_dir}' + raise OSError(message) + # Debian - elif os.path.isdir(os.path.join(venv_dir, 'local')): + if os.path.isdir(os.path.join(venv_dir, 'local')): exe_dir = os.path.join(venv_dir, 'local', 'bin') if os.path.isdir(exe_dir): return exe_dir - else: - message = f'Unable to locate executables directory within: {venv_dir}' - raise OSError(message) - else: + message = f'Unable to locate executables directory within: {venv_dir}' raise OSError(message) + message = f'Unable to locate executables directory within: {venv_dir}' + raise OSError(message) + def main(): original_backend_path = os.path.dirname(os.path.dirname(HERE)) diff --git a/docs/.hooks/expand_blocks.py b/docs/.hooks/expand_blocks.py index 58a08bd66..9bc0c3c3b 100644 --- a/docs/.hooks/expand_blocks.py +++ b/docs/.hooks/expand_blocks.py @@ -48,12 +48,12 @@ def on_config( class MyExtension(Extension): - def extendMarkdown(self, md): # noqa: N802 + def extendMarkdown(self, md): # noqa: N802, PLR6301 md.preprocessors.register(MyPreprocessor(), 'mypreprocessor', 100) class MyPreprocessor(Preprocessor): - def run(self, lines): + def run(self, lines): # noqa: PLR6301 markdown = '\n'.join(lines) markdown = _config_example_regex.sub(_config_example_replace, markdown) markdown = _code_tab_regex.sub(_code_tab_replace, markdown) diff --git a/docs/.hooks/inject_version.py b/docs/.hooks/inject_version.py index e350727b9..904e4f587 100644 --- a/docs/.hooks/inject_version.py +++ b/docs/.hooks/inject_version.py @@ -12,7 +12,7 @@ @cache def get_latest_version(): - output = subprocess.check_output(['hatch', '--no-color', 'version']).decode('utf-8').strip() + output = subprocess.check_output(['hatch', '--no-color', 'version']).decode('utf-8').strip() # noqa: S607 version = output.replace('dev', '') parts = list(map(int, version.split('.'))) diff --git a/hatch.toml b/hatch.toml index dd18aa3d5..cfc92efad 100644 --- a/hatch.toml +++ b/hatch.toml @@ -47,20 +47,18 @@ write-summary-report = "python scripts/write_coverage_summary_report.py" [envs.lint] detached = true dependencies = [ - "black>=23.1.0", "mypy>=1.0.0", - "ruff<0.0.262", + "ruff==0.1.4", ] [envs.lint.scripts] typing = "mypy --install-types --non-interactive {args:backend/src/hatchling src/hatch tests}" style = [ - "ruff {args:.}", - "black --check --diff {args:.}", + "ruff check {args:.}", + "ruff format --check --diff {args:.}", ] fmt = [ - "black {args:.}", - "ruff --fix {args:.}", - "style", + "ruff check --fix {args:.}", + "ruff format {args:.}", ] all = [ "style", diff --git a/pyproject.toml b/pyproject.toml index 422c8cbdb..2bafa40a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,72 +85,6 @@ exclude = [ "/scripts", ] -[tool.black] -line-length = 120 -skip-string-normalization = true - -[tool.ruff] -line-length = 120 -select = [ - "A", - "ARG", - "B", - "C", - "DTZ", - "E", - "EM", - "F", - "FBT", - "I", - "ICN", - "ISC", - "N", - "PLC", - "PLE", - "PLR", - "PLW", - "Q", - "RUF", - "S", - "SIM", - "T", - "TID", - "TRY", - "UP", - "W", - "YTT", -] -ignore = [ - # Allow non-abstract empty methods in abstract base classes - "B027", - # Allow boolean positional values in function calls, like `dict.get(... True)` - "FBT003", - # Ignore complexity - "C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915", - "PLW2901", # `for` loop variable overwritten -] -unfixable = [ - # Don't touch unused imports - "F401", -] - -[tool.ruff.isort] -known-first-party = ["hatch", "hatchling"] - -[tool.ruff.flake8-quotes] -inline-quotes = "single" - -[tool.ruff.flake8-tidy-imports] -ban-relative-imports = "all" - -[tool.ruff.per-file-ignores] -# Allow print/pprint -"backend/src/hatchling/bridge/app.py" = ["T201"] -"backend/tests/downstream/integrate.py" = ["T201"] -"scripts/*" = ["T201"] -# Tests can use empty string comparisons, magic values, assertions, and relative imports -"tests/**/*" = ["PLC1901", "PLR2004", "S101", "TID252"] - [tool.mypy] disallow_untyped_defs = false disallow_incomplete_defs = false diff --git a/release/macos/build_pkg.py b/release/macos/build_pkg.py index 9224b4a3f..2a4f8b4e8 100644 --- a/release/macos/build_pkg.py +++ b/release/macos/build_pkg.py @@ -31,7 +31,7 @@ def run_command(command: list[str]) -> None: - process = subprocess.run(command) + process = subprocess.run(command) # noqa: PLW1510 if process.returncode: sys.exit(process.returncode) diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 000000000..00c457b0f --- /dev/null +++ b/ruff.toml @@ -0,0 +1,593 @@ +line-length = 120 +select = [ + 'A001', + 'A002', + 'A003', + 'ARG001', + 'ARG002', + 'ARG003', + 'ARG004', + 'ARG005', + 'ASYNC100', + 'ASYNC101', + 'ASYNC102', + 'B002', + 'B003', + 'B004', + 'B005', + 'B006', + 'B007', + 'B008', + 'B009', + 'B010', + 'B011', + 'B012', + 'B013', + 'B014', + 'B015', + 'B016', + 'B017', + 'B018', + 'B019', + 'B020', + 'B021', + 'B022', + 'B023', + 'B024', + 'B025', + 'B026', + 'B028', + 'B029', + 'B030', + 'B031', + 'B032', + 'B033', + 'B034', + 'B904', + 'B905', + 'BLE001', + 'C400', + 'C401', + 'C402', + 'C403', + 'C404', + 'C405', + 'C406', + 'C408', + 'C409', + 'C410', + 'C411', + 'C413', + 'C414', + 'C415', + 'C416', + 'C417', + 'C418', + 'C419', + 'COM818', + 'DTZ001', + 'DTZ002', + 'DTZ003', + 'DTZ004', + 'DTZ005', + 'DTZ006', + 'DTZ007', + 'DTZ011', + 'DTZ012', + 'E101', + 'E112', + 'E113', + 'E115', + 'E116', + 'E201', + 'E202', + 'E211', + 'E221', + 'E222', + 'E223', + 'E224', + 'E225', + 'E226', + 'E227', + 'E228', + 'E231', + 'E241', + 'E242', + 'E251', + 'E252', + 'E261', + 'E262', + 'E265', + 'E266', + 'E271', + 'E272', + 'E273', + 'E274', + 'E275', + 'E401', + 'E402', + 'E501', + 'E701', + 'E702', + 'E703', + 'E711', + 'E712', + 'E713', + 'E714', + 'E721', + 'E722', + 'E731', + 'E741', + 'E742', + 'E743', + 'E902', + 'E999', + 'EM101', + 'EM102', + 'EM103', + 'EXE001', + 'EXE002', + 'EXE003', + 'EXE004', + 'EXE005', + 'F401', + 'F402', + 'F403', + 'F404', + 'F405', + 'F406', + 'F407', + 'F501', + 'F502', + 'F503', + 'F504', + 'F505', + 'F506', + 'F507', + 'F508', + 'F509', + 'F521', + 'F522', + 'F523', + 'F524', + 'F525', + 'F541', + 'F601', + 'F602', + 'F621', + 'F622', + 'F631', + 'F632', + 'F633', + 'F634', + 'F701', + 'F702', + 'F704', + 'F706', + 'F707', + 'F722', + 'F811', + 'F821', + 'F822', + 'F823', + 'F841', + 'F842', + 'F901', + 'FA100', + 'FA102', + 'FBT001', + 'FBT002', + 'FLY002', + 'FURB101', + 'FURB105', + 'FURB113', + 'FURB131', + 'FURB132', + 'FURB145', + 'FURB148', + 'FURB168', + 'FURB171', + 'FURB177', + 'G001', + 'G002', + 'G003', + 'G004', + 'G010', + 'G101', + 'G201', + 'G202', + 'I001', + 'I002', + 'ICN001', + 'ICN002', + 'ICN003', + 'INP001', + 'INT001', + 'INT002', + 'INT003', + 'ISC003', + 'LOG001', + 'LOG002', + 'LOG007', + 'LOG009', + 'N801', + 'N802', + 'N803', + 'N804', + 'N805', + 'N806', + 'N807', + 'N811', + 'N812', + 'N813', + 'N814', + 'N815', + 'N816', + 'N817', + 'N818', + 'N999', + 'PERF101', + 'PERF102', + 'PERF401', + 'PERF402', + 'PERF403', + 'PGH001', + 'PGH002', + 'PGH005', + 'PIE790', + 'PIE794', + 'PIE796', + 'PIE800', + 'PIE804', + 'PIE807', + 'PIE808', + 'PIE810', + 'PLC0105', + 'PLC0131', + 'PLC0132', + 'PLC0205', + 'PLC0208', + 'PLC0414', + 'PLC0415', + 'PLC1901', + 'PLC2401', + 'PLC2403', + 'PLC3002', + 'PLE0100', + 'PLE0101', + 'PLE0116', + 'PLE0117', + 'PLE0118', + 'PLE0241', + 'PLE0302', + 'PLE0307', + 'PLE0604', + 'PLE0605', + 'PLE0704', + 'PLE1205', + 'PLE1206', + 'PLE1300', + 'PLE1307', + 'PLE1310', + 'PLE1507', + 'PLE1700', + 'PLE2502', + 'PLE2510', + 'PLE2512', + 'PLE2513', + 'PLE2514', + 'PLE2515', + 'PLR0124', + 'PLR0133', + 'PLR0206', + 'PLR0402', + 'PLR0904', + 'PLR0916', + 'PLR1701', + 'PLR1706', + 'PLR1711', + 'PLR1714', + 'PLR1722', + 'PLR2004', + 'PLR5501', + 'PLR6201', + 'PLR6301', + 'PLW0108', + 'PLW0120', + 'PLW0127', + 'PLW0129', + 'PLW0131', + 'PLW0406', + 'PLW0602', + 'PLW0603', + 'PLW0604', + 'PLW0711', + 'PLW1501', + 'PLW1508', + 'PLW1509', + 'PLW1510', + 'PLW1514', + 'PLW1641', + 'PLW2101', + 'PLW2901', + 'PLW3201', + 'PLW3301', + 'PT001', + 'PT002', + 'PT003', + 'PT004', + 'PT005', + 'PT006', + 'PT007', + 'PT008', + 'PT009', + 'PT010', + 'PT011', + 'PT012', + 'PT013', + 'PT014', + 'PT015', + 'PT016', + 'PT017', + 'PT018', + 'PT019', + 'PT020', + 'PT021', + 'PT022', + 'PT023', + 'PT024', + 'PT025', + 'PT026', + 'PT027', + 'PYI001', + 'PYI002', + 'PYI003', + 'PYI004', + 'PYI005', + 'PYI006', + 'PYI007', + 'PYI008', + 'PYI009', + 'PYI010', + 'PYI011', + 'PYI012', + 'PYI013', + 'PYI014', + 'PYI015', + 'PYI016', + 'PYI017', + 'PYI018', + 'PYI019', + 'PYI020', + 'PYI021', + 'PYI024', + 'PYI025', + 'PYI026', + 'PYI029', + 'PYI030', + 'PYI032', + 'PYI033', + 'PYI034', + 'PYI035', + 'PYI036', + 'PYI041', + 'PYI042', + 'PYI043', + 'PYI044', + 'PYI045', + 'PYI046', + 'PYI047', + 'PYI048', + 'PYI049', + 'PYI050', + 'PYI051', + 'PYI052', + 'PYI053', + 'PYI054', + 'PYI055', + 'PYI056', + 'RET503', + 'RET504', + 'RET505', + 'RET506', + 'RET507', + 'RET508', + 'RSE102', + 'RUF001', + 'RUF002', + 'RUF003', + 'RUF005', + 'RUF006', + 'RUF007', + 'RUF008', + 'RUF009', + 'RUF010', + 'RUF011', + 'RUF012', + 'RUF013', + 'RUF015', + 'RUF016', + 'RUF017', + 'RUF018', + 'RUF019', + 'RUF100', + 'RUF200', + 'S101', + 'S102', + 'S103', + 'S104', + 'S105', + 'S106', + 'S107', + 'S108', + 'S110', + 'S112', + 'S113', + 'S201', + 'S301', + 'S302', + 'S303', + 'S304', + 'S305', + 'S306', + 'S307', + 'S308', + 'S310', + 'S311', + 'S312', + 'S313', + 'S314', + 'S315', + 'S316', + 'S317', + 'S318', + 'S319', + 'S320', + 'S321', + 'S323', + 'S324', + 'S501', + 'S505', + 'S506', + 'S507', + 'S508', + 'S509', + 'S601', + 'S602', + 'S604', + 'S605', + 'S606', + 'S607', + 'S608', + 'S609', + 'S612', + 'S701', + 'SIM101', + 'SIM102', + 'SIM103', + 'SIM105', + 'SIM107', + 'SIM108', + 'SIM109', + 'SIM110', + 'SIM112', + 'SIM114', + 'SIM115', + 'SIM116', + 'SIM117', + 'SIM118', + 'SIM201', + 'SIM202', + 'SIM208', + 'SIM210', + 'SIM211', + 'SIM212', + 'SIM220', + 'SIM221', + 'SIM222', + 'SIM223', + 'SIM300', + 'SIM401', + 'SIM910', + 'SLF001', + 'SLOT000', + 'SLOT001', + 'SLOT002', + 'T100', + 'T201', + 'T203', + 'TCH001', + 'TCH002', + 'TCH003', + 'TCH004', + 'TCH005', + 'TRIO100', + 'TRY002', + 'TRY003', + 'TRY004', + 'TRY200', + 'TRY201', + 'TRY300', + 'TRY301', + 'TRY302', + 'TRY400', + 'TRY401', + 'UP001', + 'UP003', + 'UP004', + 'UP005', + 'UP006', + 'UP007', + 'UP008', + 'UP009', + 'UP010', + 'UP011', + 'UP012', + 'UP013', + 'UP014', + 'UP015', + 'UP017', + 'UP018', + 'UP019', + 'UP020', + 'UP021', + 'UP022', + 'UP023', + 'UP024', + 'UP025', + 'UP026', + 'UP027', + 'UP028', + 'UP029', + 'UP030', + 'UP031', + 'UP032', + 'UP033', + 'UP034', + 'UP035', + 'UP036', + 'UP037', + 'UP038', + 'UP039', + 'UP040', + 'UP041', + 'W291', + 'W292', + 'W293', + 'W505', + 'W605', + 'YTT101', + 'YTT102', + 'YTT103', + 'YTT201', + 'YTT202', + 'YTT203', + 'YTT204', + 'YTT301', + 'YTT302', + 'YTT303', +] + +[isort] +known-first-party = ["hatch", "hatchling"] + +[flake8-quotes] +inline-quotes = "single" + +[flake8-tidy-imports] +ban-relative-imports = "all" + +[per-file-ignores] +# Allow print/pprint +"backend/src/hatchling/bridge/app.py" = ["T201"] +"backend/tests/downstream/integrate.py" = ["INP001", "T201"] +"docs/.hooks/*" = ["INP001", "T201"] +"release/macos/build_pkg.py" = ["INP001"] +"scripts/*" = ["INP001", "T201"] +"**/scripts/*" = ["INP001", "T201"] +# Tests can use empty string comparisons, magic values, assertions, and relative imports +"tests/**/*" = ["PLC1901", "PLR2004", "PLR6301", "S", "TID252"] +"backend/tests/**/*" = ["S"] + +[format] +quote-style = "single" diff --git a/scripts/bump.py b/scripts/bump.py index 30aa8ff59..625f3e422 100644 --- a/scripts/bump.py +++ b/scripts/bump.py @@ -24,8 +24,8 @@ def main(): history_file = root_dir / 'docs' / 'history' / f'{args.project}.md' if args.project == 'hatchling': - process = subprocess.run( - ['hatch', 'version', args.version], + process = subprocess.run( # noqa: PLW1510 + ['hatch', 'version', args.version], # noqa: S607 stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8', diff --git a/scripts/install_mkdocs_material_insiders.py b/scripts/install_mkdocs_material_insiders.py index c21cc8d32..87943d341 100644 --- a/scripts/install_mkdocs_material_insiders.py +++ b/scripts/install_mkdocs_material_insiders.py @@ -21,7 +21,7 @@ def main(): stderr=subprocess.STDOUT, encoding='utf-8', ) - except Exception as e: + except Exception as e: # noqa: BLE001 print(str(e).replace(TOKEN, '*****')) sys.exit(1) diff --git a/scripts/update_distributions.py b/scripts/update_distributions.py index 731e95f94..470e5828c 100644 --- a/scripts/update_distributions.py +++ b/scripts/update_distributions.py @@ -22,8 +22,8 @@ def parse_distributions(contents: str, constant: str): raise ValueError(message) block = match.group(0).replace('",\n', '",') - for line in block.splitlines()[1:-1]: - line = line.strip() + for raw_line in block.splitlines()[1:-1]: + line = raw_line.strip() if not line or line.startswith('//'): continue @@ -62,22 +62,17 @@ def main(): '# fmt: off', 'ORDERED_DISTRIBUTIONS: tuple[str, ...] = (', ] - for identifier in ordered: - output.append(f' {identifier!r},') - output.append(')') + output.extend(f' {identifier!r},' for identifier in ordered) + output.append(')') # noqa: FURB113 output.append('DISTRIBUTIONS: dict[str, dict[tuple[str, ...], str]] = {') for identifier, data in distributions.items(): output.append(f' {identifier!r}: {{') - for d, source in data: - output.append(f' {d!r}:') - output.append(f' {source!r},') - + output.extend((f' {d!r}:', f' {source!r},')) output.append(' },') - output.append('}') - output.append('') + output.extend(('}', '')) output = '\n'.join(output) with open(OUTPUT_FILE, 'w') as f: diff --git a/scripts/validate_history.py b/scripts/validate_history.py index ef2eca32c..35f2dc4b6 100644 --- a/scripts/validate_history.py +++ b/scripts/validate_history.py @@ -15,15 +15,17 @@ def main(): current_pattern = HEADER_PATTERN.format(package=package) with history_file.open('r', encoding='utf-8') as f: - for line in f: - line = line.strip() + for raw_line in f: + line = raw_line.strip() if not line: continue - elif line.startswith('## '): + + if line.startswith('## '): _, _, header = line.partition(' ') if header == 'Unreleased': continue - elif not re.search(current_pattern, header): + + if not re.search(current_pattern, header): print('Invalid header:') print(header) sys.exit(1) diff --git a/src/hatch/cli/__init__.py b/src/hatch/cli/__init__.py index 68da72446..92f92fbb1 100644 --- a/src/hatch/cli/__init__.py +++ b/src/hatch/cli/__init__.py @@ -108,7 +108,7 @@ def hatch(ctx: click.Context, env_name, project, verbose, quiet, color, interact app = Application(ctx.exit, verbose - quiet, color, interactive) app.env_active = os.environ.get(AppEnvVars.ENV_ACTIVE) - if app.env_active and ctx.get_parameter_source('env_name').name == 'DEFAULT': # type: ignore + if app.env_active and ctx.get_parameter_source('env_name').name == 'DEFAULT': app.env = app.env_active else: app.env = env_name @@ -162,8 +162,9 @@ def hatch(ctx: click.Context, env_name, project, verbose, quiet, color, interact if app.config.mode == 'local': return + # The following logic is mostly duplicated for each branch so coverage can be asserted - elif app.config.mode == 'project': + if app.config.mode == 'project': if not app.config.project: app.display_warning('Mode is set to `project` but no project is set, defaulting to the current directory') return @@ -175,7 +176,8 @@ def hatch(ctx: click.Context, env_name, project, verbose, quiet, color, interact app.project = possible_project return - elif app.config.mode == 'aware' and app.project.root is None: + + if app.config.mode == 'aware' and app.project.root is None: if not app.config.project: app.display_warning('Mode is set to `aware` but no project is set, defaulting to the current directory') return @@ -211,7 +213,7 @@ def hatch(ctx: click.Context, env_name, project, verbose, quiet, color, interact def main(): # no cov try: return hatch(prog_name='hatch', windows_expand_args=False) - except Exception: + except Exception: # noqa: BLE001 from rich.console import Console console = Console() diff --git a/src/hatch/cli/application.py b/src/hatch/cli/application.py index 62cd85a1e..8dac75b8b 100644 --- a/src/hatch/cli/application.py +++ b/src/hatch/cli/application.py @@ -89,7 +89,7 @@ def prepare_internal_environment(self, env_name: str, config: dict[str, Any] | N ) try: environment.check_compatibility() - except Exception as e: + except Exception as e: # noqa: BLE001 self.abort(f'Internal environment `{env_name}` is incompatible: {e}') self.prepare_environment(environment) @@ -144,17 +144,18 @@ def run_shell_commands( with environment.command_context(): try: resolved_commands = list(environment.resolve_commands(commands)) - except Exception as e: + except Exception as e: # noqa: BLE001 self.abort(str(e)) first_error_code = None should_display_command = self.verbose or len(resolved_commands) > 1 - for i, command in enumerate(resolved_commands, 1): + for i, raw_command in enumerate(resolved_commands, 1): if should_display_command: - self.display(f'{source} [{i}] | {command}') + self.display(f'{source} [{i}] | {raw_command}') + command = raw_command continue_on_error = force_continue - if command.startswith('- '): + if raw_command.startswith('- '): continue_on_error = True command = command[2:] @@ -163,7 +164,8 @@ def run_shell_commands( first_error_code = first_error_code or process.returncode if continue_on_error: continue - elif show_code_on_error: + + if show_code_on_error: self.abort(f'Failed with exit code: {process.returncode}', code=process.returncode) else: self.abort(code=process.returncode) @@ -237,8 +239,7 @@ def ensure_plugin_dependencies(self, dependencies: list[Requirement], *, wait_me # Default to -1 verbosity add_verbosity_flag(command, self.verbosity, adjustment=-1) - for dependency in dependencies: - command.append(str(dependency)) + command.extend(str(dependency) for dependency in dependencies) with self.status(wait_message): self.platform.check_command(command) @@ -250,10 +251,10 @@ def get_env_directory(self, environment_type): path = Path(directories[environment_type]).expand() if os.path.isabs(path): return path - else: - return self.project.location / path - else: - return self.data_dir / 'env' / environment_type + + return self.project.location / path + + return self.data_dir / 'env' / environment_type def get_python_manager(self, directory: str | None = None): from hatch.python.core import PythonManager @@ -261,10 +262,11 @@ def get_python_manager(self, directory: str | None = None): configured_dir = directory or self.config.dirs.python if configured_dir == 'shared': return PythonManager(Path.home() / '.pythons') - elif configured_dir == 'isolated': + + if configured_dir == 'isolated': return PythonManager(self.data_dir / 'pythons') - else: - return PythonManager(Path(configured_dir).expand()) + + return PythonManager(Path(configured_dir).expand()) @cached_property def shell_data(self) -> tuple[str, str]: @@ -346,8 +348,8 @@ def _metadata_file(self, environment: EnvironmentInterface) -> Path: if isinstance(environment, InternalEnvironment) and environment.config.get('skip-install'): return self.__data_dir / '.internal' / f'{environment.name}.json' - else: - return self._storage_dir / environment.config['type'] / f'{environment.name}.json' + + return self._storage_dir / environment.config['type'] / f'{environment.name}.json' @cached_property def _storage_dir(self) -> Path: diff --git a/src/hatch/cli/config/__init__.py b/src/hatch/cli/config/__init__.py index 69a3ba488..424968e96 100644 --- a/src/hatch/cli/config/__init__.py +++ b/src/hatch/cli/config/__init__.py @@ -133,7 +133,7 @@ def set_value(app, key, value): app.abort() else: if not user_config['project'] and setting_project_location: - project = list(branch_config_root['projects'])[0] + project = next(iter(branch_config_root['projects'])) user_config['project'] = project branch_config_root['project'] = project diff --git a/src/hatch/cli/dep/__init__.py b/src/hatch/cli/dep/__init__.py index ace7b7654..46278d55e 100644 --- a/src/hatch/cli/dep/__init__.py +++ b/src/hatch/cli/dep/__init__.py @@ -124,8 +124,8 @@ def requirements(app, project_only, env_only, features, all_features): all_requirements = [] if features: - for feature in features: - feature = normalize_project_name(feature) + for raw_feature in features: + feature = normalize_project_name(raw_feature) if feature not in optional_dependencies_complex: app.abort(f'Feature `{feature}` is not defined in field `project.optional-dependencies`') diff --git a/src/hatch/cli/env/create.py b/src/hatch/cli/env/create.py index 0921f0f67..593823f01 100644 --- a/src/hatch/cli/env/create.py +++ b/src/hatch/cli/env/create.py @@ -25,12 +25,12 @@ def create(app, env_name): try: environment.check_compatibility() - except Exception as e: + except Exception as e: # noqa: BLE001 if root_env_name in project_config.matrices: incompatible[env_name] = str(e) continue - else: - app.abort(f'Environment `{env_name}` is incompatible: {e}') + + app.abort(f'Environment `{env_name}` is incompatible: {e}') if environment.exists(): app.display_warning(f'Environment `{env_name}` already exists') diff --git a/src/hatch/cli/env/find.py b/src/hatch/cli/env/find.py index c9f7be897..7316be387 100644 --- a/src/hatch/cli/env/find.py +++ b/src/hatch/cli/env/find.py @@ -24,7 +24,7 @@ def find(app, env_name): try: environment.check_compatibility() - except Exception: # noqa: S112 + except Exception: # noqa: BLE001, S112 continue app.display(environment.find()) diff --git a/src/hatch/cli/env/prune.py b/src/hatch/cli/env/prune.py index ab575a0b4..55753b76e 100644 --- a/src/hatch/cli/env/prune.py +++ b/src/hatch/cli/env/prune.py @@ -33,7 +33,7 @@ def prune(app): try: environment.check_compatibility() - except Exception: # noqa: S112 + except Exception: # noqa: BLE001, S112 continue if environment.exists() or environment.build_environment_exists(): diff --git a/src/hatch/cli/env/remove.py b/src/hatch/cli/env/remove.py index c2a2199ff..f04325632 100644 --- a/src/hatch/cli/env/remove.py +++ b/src/hatch/cli/env/remove.py @@ -25,7 +25,7 @@ def remove(ctx, env_name): try: environment.check_compatibility() - except Exception: # noqa: S112 + except Exception: # noqa: BLE001, S112 continue if environment.exists() or environment.build_environment_exists(): diff --git a/src/hatch/cli/env/run.py b/src/hatch/cli/env/run.py index 8d6193030..a6d90d343 100644 --- a/src/hatch/cli/env/run.py +++ b/src/hatch/cli/env/run.py @@ -163,12 +163,12 @@ def run( try: environment.check_compatibility() - except Exception as e: + except Exception as e: # noqa: BLE001 if ignore_compat or matrix_selected: incompatible[environment.name] = str(e) continue - else: - app.abort(f'Environment `{env_name}` is incompatible: {e}') + + app.abort(f'Environment `{env_name}` is incompatible: {e}') any_compatible = True if should_display_header: diff --git a/src/hatch/cli/env/show.py b/src/hatch/cli/env/show.py index 04c4918a0..2c0ca9fc5 100644 --- a/src/hatch/cli/env/show.py +++ b/src/hatch/cli/env/show.py @@ -52,8 +52,6 @@ def show(app, envs, force_ascii, as_json): app.display(json.dumps(contextual_config, separators=(',', ':'))) return - import contextlib - from packaging.requirements import InvalidRequirement, Requirement from hatchling.metadata.utils import get_normalized_dependency, normalize_project_name @@ -105,10 +103,12 @@ def show(app, envs, force_ascii, as_json): if dependencies: normalized_dependencies = set() for dependency in dependencies: - with contextlib.suppress(InvalidRequirement): - dependency = get_normalized_dependency(Requirement(dependency)) - - normalized_dependencies.add(dependency) + try: + req = Requirement(dependency) + except InvalidRequirement: + normalized_dependencies.add(dependency) + else: + normalized_dependencies.add(get_normalized_dependency(req)) matrix_columns['Dependencies'][i] = '\n'.join(sorted(normalized_dependencies)) diff --git a/src/hatch/cli/new/__init__.py b/src/hatch/cli/new/__init__.py index f07731012..f1f2d21dd 100644 --- a/src/hatch/cli/new/__init__.py +++ b/src/hatch/cli/new/__init__.py @@ -61,7 +61,7 @@ def new(app, name, location, interactive, feature_cli, initialize, setuptools_op ) as venv: app.platform.run_command(['python', '-m', 'pip', 'install', '-q', 'setuptools']) migrate(str(location), setuptools_options, venv.sys_path) - except Exception as e: + except Exception as e: # noqa: BLE001 app.display_error(f'Could not automatically migrate from setuptools: {e}') if name == 'temporary': name = app.prompt('Project name') @@ -118,10 +118,12 @@ def new(app, name, location, interactive, feature_cli, initialize, setuptools_op template_files = [] for template in templates: - for template_file in template.get_files(config=deepcopy(template_config)): - if template_file.__class__ is not File: - template_file = template_file(deepcopy(template_config), template.plugin_config) - + for possible_template_file in template.get_files(config=deepcopy(template_config)): + template_file = ( + possible_template_file(deepcopy(template_config), template.plugin_config) + if possible_template_file.__class__ is not File + else possible_template_file + ) if template_file.path is None or (initialize and str(template_file.path) != 'pyproject.toml'): continue diff --git a/src/hatch/cli/new/migrate.py b/src/hatch/cli/new/migrate.py index da5433219..f11aada22 100644 --- a/src/hatch/cli/new/migrate.py +++ b/src/hatch/cli/new/migrate.py @@ -17,9 +17,9 @@ def _apply_env_vars(kwargs): def _parse_dependencies(dependency_definition): dependencies = [] for line in dependency_definition.splitlines(): - line = line.split(' #', 1)[0].strip() - if line: - dependencies.append(line) + dependency = line.split(' #', 1)[0].strip() + if dependency: + dependencies.append(dependency) return dependencies @@ -94,8 +94,8 @@ def _parse_setup_cfg(kwargs): if 'packages' in options and 'packages' not in kwargs: packages = [] - for package in options['packages'].strip().splitlines(): - package = package.replace('find:', '', 1).replace('find_namespace:', '', 1).strip() + for package_spec in options['packages'].strip().splitlines(): + package = package_spec.replace('find:', '', 1).replace('find_namespace:', '', 1).strip() if package: packages.append(package) @@ -165,11 +165,13 @@ def setup(**kwargs): collaborator_names = [] collaborator_emails = [] if collaborator in kwargs: - for collaborator_name in kwargs[collaborator].split(','): - collaborator_names.append(collaborator_name.strip()) + collaborator_names.extend( + collaborator_name.strip() for collaborator_name in kwargs[collaborator].split(',') + ) if f'{collaborator}_email' in kwargs: - for collaborator_email in kwargs[f'{collaborator}_email'].split(','): - collaborator_emails.append(collaborator_email.strip()) + collaborator_emails.extend( + collaborator_email.strip() for collaborator_email in kwargs[f'{collaborator}_email'].split(',') + ) for collaborator_name, collaborator_email in itertools.zip_longest(collaborator_names, collaborator_emails): data = {} @@ -224,9 +226,8 @@ def setup(**kwargs): if 'entry_points' in kwargs and isinstance(kwargs['entry_points'], dict): entry_points = {} - for entry_point, definitions in kwargs['entry_points'].items(): - if isinstance(definitions, str): - definitions = [definitions] + for entry_point, raw_definitions in kwargs['entry_points'].items(): + definitions = [raw_definitions] if isinstance(raw_definitions, str) else raw_definitions definitions = dict(sorted(d.replace(' ', '').split('=', 1) for d in definitions)) if entry_point == 'console_scripts': @@ -305,7 +306,7 @@ def setup(**kwargs): current_contents = f.read() for section in ('build-system', 'project'): - for pattern in (fr'^\[{section}].*?(?=^\[)', fr'^\[{section}].*'): + for pattern in (rf'^\[{section}].*?(?=^\[)', rf'^\[{section}].*'): current_contents = re.sub(pattern, '', current_contents, flags=re.MULTILINE | re.DOTALL) output += f'\n{current_contents}' diff --git a/src/hatch/cli/project/metadata.py b/src/hatch/cli/project/metadata.py index 4e9acb7a0..b29d5efeb 100644 --- a/src/hatch/cli/project/metadata.py +++ b/src/hatch/cli/project/metadata.py @@ -32,7 +32,7 @@ def metadata(app, field): environment = app.get_environment() try: environment.check_compatibility() - except Exception as e: + except Exception as e: # noqa: BLE001 app.abort(f'Environment `{environment.name}` is incompatible: {e}') with app.status_if( diff --git a/src/hatch/cli/python/install.py b/src/hatch/cli/python/install.py index df46a5010..854b6a03e 100644 --- a/src/hatch/cli/python/install.py +++ b/src/hatch/cli/python/install.py @@ -79,7 +79,8 @@ def install(app: Application, *, names: tuple[str, ...], private: bool, update: if not needs_update: app.display_warning(f'The latest version is already installed: {name}') continue - elif not (update or app.confirm(f'Update {name}?')): + + if not (update or app.confirm(f'Update {name}?')): app.abort(f'Distribution is already installed: {name}') with app.status(f'{"Updating" if needs_update else "Installing"} {name}'): diff --git a/src/hatch/cli/terminal.py b/src/hatch/cli/terminal.py index d6b326288..e6bf95673 100644 --- a/src/hatch/cli/terminal.py +++ b/src/hatch/cli/terminal.py @@ -4,22 +4,24 @@ from abc import ABC, abstractmethod from functools import cached_property from textwrap import indent as indent_text -from typing import Callable +from typing import TYPE_CHECKING, Callable import click from rich.console import Console from rich.errors import StyleSyntaxError -from rich.status import Status from rich.style import Style from rich.text import Text +if TYPE_CHECKING: + from rich.status import Status + class TerminalStatus(ABC): @abstractmethod def stop(self) -> None: ... - def __enter__(self) -> TerminalStatus: + def __enter__(self) -> TerminalStatus: # noqa: PYI034 return self @abstractmethod @@ -80,7 +82,7 @@ def __call__(self, message: str, final_text: str = '') -> BorrowedStatus: self.__messages.append((Text(message, style=self.__waiting_style), final_text)) return self - def __enter__(self) -> BorrowedStatus: + def __enter__(self) -> BorrowedStatus: # noqa: PYI034 if not self.__messages: return self @@ -121,7 +123,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): self.__status.start() def __active(self) -> bool: - return self.__status is not None and self.__status._live.is_started + return self.__status is not None and self.__status._live.is_started # noqa: SLF001 def __output(self, text): self.__console.stderr = True @@ -189,14 +191,14 @@ def initialize_styles(self, styles: dict): # no cov default_level = getattr(self, attribute, None) if default_level: try: - style = Style.parse(style) + parsed_style = Style.parse(style) except StyleSyntaxError as e: # no cov errors.append(f'Invalid style definition for `{option}`, defaulting to `{default_level}`: {e}') - style = Style.parse(default_level) - else: - attribute = f'_style_{option}' + parsed_style = Style.parse(default_level) - setattr(self, attribute, style) + setattr(self, attribute, parsed_style) + else: + setattr(self, attribute, f'_style_{option}') return errors @@ -246,7 +248,8 @@ def display_debug(self, text='', level=1, *, stderr=True, indent=None, link=None if not 1 <= level <= 3: # noqa: PLR2004 error_message = 'Debug output can only have verbosity levels between 1 and 3 (inclusive)' raise ValueError(error_message) - elif self.verbosity < level: + + if self.verbosity < level: return self._output(text, self._style_level_debug, stderr=stderr, indent=indent, link=link, **kwargs) @@ -296,10 +299,7 @@ def display_table(self, title, columns, *, show_lines=False, column_options=None return for i in range(num_rows or max(map(max, columns.values())) + 1): - row = [] - for indices in columns.values(): - row.append(indices.get(i, '')) - + row = [indices.get(i, '') for indices in columns.values()] if any(row): table.add_row(*row) diff --git a/src/hatch/cli/version/__init__.py b/src/hatch/cli/version/__init__.py index 3da30b1b2..c79d3e264 100644 --- a/src/hatch/cli/version/__init__.py +++ b/src/hatch/cli/version/__init__.py @@ -41,7 +41,7 @@ def version(app, desired_version): environment = app.get_environment() try: environment.check_compatibility() - except Exception as e: + except Exception as e: # noqa: BLE001 app.abort(f'Environment `{environment.name}` is incompatible: {e}') with app.status_if( diff --git a/src/hatch/config/model.py b/src/hatch/config/model.py index 2de330957..7b4d96060 100644 --- a/src/hatch/config/model.py +++ b/src/hatch/config/model.py @@ -471,8 +471,11 @@ def name(self): import subprocess try: - name = subprocess.check_output(['git', 'config', '--get', 'user.name'], text=True).strip() - except Exception: + name = subprocess.check_output( + ['git', 'config', '--get', 'user.name'], # noqa: S607 + text=True, + ).strip() + except Exception: # noqa: BLE001 name = 'U.N. Owen' self._field_name = self.raw_data['name'] = name @@ -499,8 +502,11 @@ def email(self): import subprocess try: - email = subprocess.check_output(['git', 'config', '--get', 'user.email'], text=True).strip() - except Exception: + email = subprocess.check_output( + ['git', 'config', '--get', 'user.email'], # noqa: S607 + text=True, + ).strip() + except Exception: # noqa: BLE001 email = 'void@some.where' self._field_email = self.raw_data['email'] = email diff --git a/src/hatch/config/user.py b/src/hatch/config/user.py index f01226edd..70d4fd365 100644 --- a/src/hatch/config/user.py +++ b/src/hatch/config/user.py @@ -1,4 +1,6 @@ -from typing import Optional, cast +from __future__ import annotations + +from typing import cast from hatch.config.model import RootConfig from hatch.utils.fs import Path @@ -6,8 +8,8 @@ class ConfigFile: - def __init__(self, path: Optional[Path] = None): - self._path: Optional[Path] = path + def __init__(self, path: Path | None = None): + self._path: Path | None = path self.model = cast(RootConfig, None) @property diff --git a/src/hatch/env/collectors/custom.py b/src/hatch/env/collectors/custom.py index 2fa7ea4a2..287c3a938 100644 --- a/src/hatch/env/collectors/custom.py +++ b/src/hatch/env/collectors/custom.py @@ -22,7 +22,8 @@ def __new__( # type: ignore if not isinstance(custom_script, str): message = f'Option `path` for environment collector `{cls.PLUGIN_NAME}` must be a string' raise TypeError(message) - elif not custom_script: + + if not custom_script: message = f'Option `path` for environment collector `{cls.PLUGIN_NAME}` must not be empty if defined' raise ValueError(message) diff --git a/src/hatch/env/collectors/default.py b/src/hatch/env/collectors/default.py index 40c9d493c..682c23dcb 100644 --- a/src/hatch/env/collectors/default.py +++ b/src/hatch/env/collectors/default.py @@ -5,7 +5,7 @@ class DefaultEnvironmentCollector(EnvironmentCollectorInterface): PLUGIN_NAME = 'default' - def get_initial_config(self): + def get_initial_config(self): # noqa: PLR6301 config = {} ensure_valid_environment(config) diff --git a/src/hatch/env/collectors/plugin/interface.py b/src/hatch/env/collectors/plugin/interface.py index fae9af80e..094f49dd0 100644 --- a/src/hatch/env/collectors/plugin/interface.py +++ b/src/hatch/env/collectors/plugin/interface.py @@ -49,7 +49,7 @@ def config(self) -> dict: """ return self.__config - def get_initial_config(self) -> dict[str, dict]: + def get_initial_config(self) -> dict[str, dict]: # noqa: PLR6301 """ Returns configuration for environments keyed by the environment or matrix name. """ diff --git a/src/hatch/env/context.py b/src/hatch/env/context.py index 409bf8076..0f385ae68 100644 --- a/src/hatch/env/context.py +++ b/src/hatch/env/context.py @@ -15,7 +15,7 @@ def __init__(self, environment): self.environment = environment self.CONTEXT_NAME = f'environment_{environment.PLUGIN_NAME}' - def formatters(self): + def formatters(self): # noqa: PLR6301 """ This returns a mapping of supported field names to their respective formatting functions. Each function accepts 2 arguments: @@ -36,11 +36,11 @@ def get_formatters(self): formatters.update(self.formatters()) return formatters - def __format_args(self, value, data): + def __format_args(self, value, data): # noqa: PLR6301 if value is not None: return value - else: - return data or '' + + return data or '' def __format_env_name(self, value, data): # noqa: ARG002 return self.environment.name @@ -56,11 +56,12 @@ def __format_matrix(self, value, data): # noqa: ARG002 variable, separator, default = data.partition(':') if variable in self.environment.matrix_variables: return self.environment.matrix_variables[variable] - elif not separator: + + if not separator: message = f'Nonexistent matrix variable must set a default: {variable}' raise ValueError(message) - else: - return default + + return default def __format_verbosity(self, value, data): # noqa: ARG002 if not data: @@ -70,7 +71,8 @@ def __format_verbosity(self, value, data): # noqa: ARG002 if modifier != 'flag': message = f'Unknown verbosity modifier: {modifier}' raise ValueError(message) - elif not adjustment: + + if not adjustment: adjustment = '0' try: diff --git a/src/hatch/env/internal/__init__.py b/src/hatch/env/internal/__init__.py index 21b66b0f1..2841bb882 100644 --- a/src/hatch/env/internal/__init__.py +++ b/src/hatch/env/internal/__init__.py @@ -11,6 +11,6 @@ def get_internal_environment_class(env_name: str) -> type[InternalEnvironment]: from hatch.env.internal.build import InternalBuildEnvironment return InternalBuildEnvironment - else: # no cov - message = f'Unknown internal environment: {env_name}' - raise ValueError(message) + + message = f'Unknown internal environment: {env_name}' + raise ValueError(message) diff --git a/src/hatch/env/internal/build.py b/src/hatch/env/internal/build.py index 44862a582..2b0f23c1f 100644 --- a/src/hatch/env/internal/build.py +++ b/src/hatch/env/internal/build.py @@ -4,7 +4,7 @@ class InternalBuildEnvironment(InternalEnvironment): - def get_base_config(self) -> dict: + def get_base_config(self) -> dict: # noqa: PLR6301 return { 'skip-install': True, 'dependencies': ['build[virtualenv]>=1.0.3'], diff --git a/src/hatch/env/internal/interface.py b/src/hatch/env/internal/interface.py index f7f6ef34b..6379aac64 100644 --- a/src/hatch/env/internal/interface.py +++ b/src/hatch/env/internal/interface.py @@ -1,11 +1,12 @@ from __future__ import annotations +from abc import ABC, abstractmethod from functools import cached_property from hatch.env.virtual import VirtualEnvironment -class InternalEnvironment(VirtualEnvironment): +class InternalEnvironment(VirtualEnvironment, ABC): @cached_property def config(self) -> dict: config = {'type': 'virtual', 'template': self.name} @@ -13,5 +14,6 @@ def config(self) -> dict: config.update(super().config) return config + @abstractmethod def get_base_config(self) -> dict: - return {} + ... diff --git a/src/hatch/env/plugin/interface.py b/src/hatch/env/plugin/interface.py index ae6897c9f..d0d8f39e0 100644 --- a/src/hatch/env/plugin/interface.py +++ b/src/hatch/env/plugin/interface.py @@ -420,23 +420,27 @@ def features(self): if not isinstance(feature, str): message = f'Feature #{i} of field `tool.hatch.envs.{self.name}.features` must be a string' raise TypeError(message) - elif not feature: + + if not feature: message = f'Feature #{i} of field `tool.hatch.envs.{self.name}.features` cannot be an empty string' raise ValueError(message) - if not self.metadata.hatch.metadata.allow_ambiguous_features: - feature = normalize_project_name(feature) + normalized_feature = ( + feature + if self.metadata.hatch.metadata.allow_ambiguous_features + else normalize_project_name(feature) + ) if ( not self.metadata.hatch.metadata.hook_config - and feature not in self.metadata.core.optional_dependencies + and normalized_feature not in self.metadata.core.optional_dependencies ): message = ( - f'Feature `{feature}` of field `tool.hatch.envs.{self.name}.features` is not ' + f'Feature `{normalized_feature}` of field `tool.hatch.envs.{self.name}.features` is not ' f'defined in field `project.optional-dependencies`' ) raise ValueError(message) - all_features.add(feature) + all_features.add(normalized_feature) self._features = sorted(all_features) @@ -699,7 +703,7 @@ def get_build_process( """ return self.platform.capture_process(self.construct_build_command(**kwargs)) - def build_environment_exists(self): + def build_environment_exists(self): # noqa: PLR6301 """ If the [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment) @@ -770,7 +774,7 @@ def expand_command(self, command): yield self.metadata.context.format(command, args=args).strip() def construct_build_command( - self, + self, # noqa: PLR6301 *, directory=None, targets=(), @@ -900,7 +904,8 @@ def __exit__(self, exc_type, exc_value, traceback): def expand_script_commands(env_name, script_name, commands, config, seen, active): if script_name in seen: return seen[script_name] - elif script_name in active: + + if script_name in active: active.append(script_name) message = f'Circular expansion detected for field `tool.hatch.envs.{env_name}.scripts`: {" -> ".join(active)}' diff --git a/src/hatch/env/utils.py b/src/hatch/env/utils.py index bd136bb9c..9328ccfe6 100644 --- a/src/hatch/env/utils.py +++ b/src/hatch/env/utils.py @@ -9,10 +9,11 @@ def get_verbosity_flag(verbosity: int, *, adjustment=0) -> str: verbosity += adjustment if not verbosity: return '' - elif verbosity > 0: + + if verbosity > 0: return f'-{"v" * abs(min(verbosity, 3))}' - else: - return f'-{"q" * abs(max(verbosity, -3))}' + + return f'-{"q" * abs(max(verbosity, -3))}' def add_verbosity_flag(command: list[str], verbosity: int, *, adjustment=0): diff --git a/src/hatch/env/virtual.py b/src/hatch/env/virtual.py index ec941f939..583b54238 100644 --- a/src/hatch/env/virtual.py +++ b/src/hatch/env/virtual.py @@ -253,11 +253,15 @@ def _get_concrete_interpreter_path(self, python_version: str = '') -> str | None if (concrete_path := resolver('')) is not None: return concrete_path + return None + def _resolve_external_interpreter_path(self, python_version: str) -> str | None: if (existing_path := self._find_existing_interpreter(python_version)) is not None: self.upgrade_possible_internal_python(existing_path) return existing_path + return None + def _resolve_internal_interpreter_path(self, python_version: str) -> str | None: if (available_distribution := self._get_available_distribution(python_version)) is not None: with self.app.status(f'Installing Python distribution: {available_distribution}'): @@ -265,6 +269,8 @@ def _resolve_internal_interpreter_path(self, python_version: str) -> str | None: return str(dist.python_path) + return None + def _find_existing_interpreter(self, python_version: str = '') -> str | None: from virtualenv.discovery import builtin as virtualenv_discovery @@ -316,6 +322,8 @@ def _get_available_distribution(self, python_version: str = '') -> str | None: return available_distribution + return None + def _is_stable_path(self, executable: str) -> bool: path = Path(executable).resolve() parents = path.parents diff --git a/src/hatch/index/core.py b/src/hatch/index/core.py index b222dde99..1fa70713a 100644 --- a/src/hatch/index/core.py +++ b/src/hatch/index/core.py @@ -1,9 +1,12 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import httpx import hyperlink -from hatch.utils.fs import Path +if TYPE_CHECKING: + from hatch.utils.fs import Path class IndexURLs: diff --git a/src/hatch/index/publish.py b/src/hatch/index/publish.py index 37cc41b9e..69ad140e2 100644 --- a/src/hatch/index/publish.py +++ b/src/hatch/index/publish.py @@ -60,8 +60,6 @@ def get_sdist_form_data(artifact): if tar_info.isfile(): pkg_info_dir_parts.append(tar_info.name.split('/', 1)[0]) break - else: # no cov - pass else: # no cov message = f'Could not find any files in sdist: {artifact}' raise ArtifactMetadataError(message) diff --git a/src/hatch/plugin/utils.py b/src/hatch/plugin/utils.py index d654cf9e3..5a097fe6e 100644 --- a/src/hatch/plugin/utils.py +++ b/src/hatch/plugin/utils.py @@ -35,11 +35,12 @@ def load_plugin_from_script( if not subclasses: message = f'Unable to find a subclass of `{plugin_class.__name__}` in `{script_name}`: {path}' raise ValueError(message) - elif len(subclasses) > 1: + + if len(subclasses) > 1: message = ( f'Multiple subclasses of `{plugin_class.__name__}` found in `{script_name}`, ' f'select one by defining a function named `{plugin_finder}`: {path}' ) raise ValueError(message) - else: - return subclasses[0] + + return subclasses[0] diff --git a/src/hatch/project/config.py b/src/hatch/project/config.py index 2e2283221..d8b0a1573 100644 --- a/src/hatch/project/config.py +++ b/src/hatch/project/config.py @@ -161,7 +161,7 @@ def envs(self): generated_envs = {} final_config = {} cached_overrides = {} - for env_name, initial_config in config.items(): + for env_name, raw_initial_config in config.items(): current_cached_overrides = cached_overrides[env_name] = { 'platform': [], 'env': [], @@ -170,13 +170,14 @@ def envs(self): } # Only shallow copying is necessary since we just want to modify keys - initial_config = initial_config.copy() + initial_config = raw_initial_config.copy() matrix_name_format = initial_config.pop('matrix-name-format', '{value}') if not isinstance(matrix_name_format, str): message = f'Field `tool.hatch.envs.{env_name}.matrix-name-format` must be a string' raise TypeError(message) - elif '{value}' not in matrix_name_format: + + if '{value}' not in matrix_name_format: message = ( f'Field `tool.hatch.envs.{env_name}.matrix-name-format` must ' f'contain at least the `{{value}}` placeholder' @@ -198,7 +199,8 @@ def envs(self): if not isinstance(options, dict): message = f'Field `tool.hatch.envs.{env_name}.overrides.platform.{platform}` must be a table' raise TypeError(message) - elif platform != current_platform: + + if platform != current_platform: continue apply_overrides(env_name, 'platform', platform, current_platform, options, initial_config) @@ -214,7 +216,8 @@ def envs(self): if not isinstance(options, dict): message = f'Field `tool.hatch.envs.{env_name}.overrides.env.{env_var}` must be a table' raise TypeError(message) - elif env_var not in environ: + + if env_var not in environ: continue apply_overrides(env_name, 'env', env_var, environ[env_var], options, initial_config) @@ -241,11 +244,13 @@ def envs(self): matrix_data = all_matrices[env_name] = {'config': deepcopy(initial_config)} all_envs = matrix_data['envs'] = {} - for i, matrix in enumerate(matrices, 1): + for i, raw_matrix in enumerate(matrices, 1): + matrix = raw_matrix if not isinstance(matrix, dict): message = f'Entry #{i} in field `tool.hatch.envs.{env_name}.matrix` must be a table' raise TypeError(message) - elif not matrix: + + if not matrix: message = f'Matrix #{i} in field `tool.hatch.envs.{env_name}.matrix` cannot be empty' raise ValueError(message) @@ -256,13 +261,15 @@ def envs(self): f'cannot be an empty string' ) raise ValueError(message) - elif not isinstance(values, list): + + if not isinstance(values, list): message = ( f'Variable `{variable}` in matrix #{i} in field `tool.hatch.envs.{env_name}.matrix` ' f'must be an array' ) raise TypeError(message) - elif not values: + + if not values: message = ( f'Variable `{variable}` in matrix #{i} in field `tool.hatch.envs.{env_name}.matrix` ' f'cannot be empty' @@ -277,18 +284,21 @@ def envs(self): f'`tool.hatch.envs.{env_name}.matrix` must be a string' ) raise TypeError(message) - elif not value: + + if not value: message = ( f'Value #{k} of variable `{variable}` in matrix #{i} in field ' f'`tool.hatch.envs.{env_name}.matrix` cannot be an empty string' ) raise ValueError(message) - elif value in existing_values: + + if value in existing_values: message = ( f'Value #{k} of variable `{variable}` in matrix #{i} in field ' f'`tool.hatch.envs.{env_name}.matrix` is a duplicate' ) raise ValueError(message) + existing_values.add(value) variables = {} @@ -327,7 +337,8 @@ def envs(self): f'Field `tool.hatch.envs.{env_name}.overrides.matrix.{variable}` must be a table' ) raise TypeError(message) - elif variable not in variables: + + if variable not in variables: continue apply_overrides( @@ -354,7 +365,8 @@ def envs(self): if not isinstance(options, dict): message = f'Field `tool.hatch.envs.{env_name}.overrides.name.{pattern}` must be a table' raise TypeError(message) - elif not re.search(pattern, new_env_name): + + if not re.search(pattern, new_env_name): continue apply_overrides(env_name, 'name', pattern, new_env_name, options, new_config) @@ -466,7 +478,8 @@ def finalize_env_overrides(self, option_types): def expand_script_commands(script_name, commands, config, seen, active): if script_name in seen: return seen[script_name] - elif script_name in active: + + if script_name in active: active.append(script_name) message = f'Circular expansion detected for field `tool.hatch.scripts`: {" -> ".join(active)}' @@ -499,7 +512,8 @@ def expand_script_commands(script_name, commands, config, seen, active): def _populate_default_env_values(env_name, data, config, seen, active): if env_name in seen: return - elif data.pop('detached', False): + + if data.pop('detached', False): data['template'] = env_name data['skip-install'] = True @@ -507,12 +521,14 @@ def _populate_default_env_values(env_name, data, config, seen, active): if template_name not in config: message = f'Field `tool.hatch.envs.{env_name}.template` refers to an unknown environment `{template_name}`' raise ValueError(message) - elif env_name in active: + + if env_name in active: active.append(env_name) message = f'Circular inheritance detected for field `tool.hatch.envs.*.template`: {" -> ".join(active)}' raise ValueError(message) - elif template_name == env_name: + + if template_name == env_name: ensure_valid_environment(data) seen.add(env_name) return @@ -525,7 +541,8 @@ def _populate_default_env_values(env_name, data, config, seen, active): for key, value in template_config.items(): if key == 'matrix': continue - elif key == 'scripts': + + if key == 'scripts': scripts = data['scripts'] if 'scripts' in data else data.setdefault('scripts', {}) for script, commands in value.items(): scripts.setdefault(script, commands) diff --git a/src/hatch/project/core.py b/src/hatch/project/core.py index 97c53a46c..a4dc2357d 100644 --- a/src/hatch/project/core.py +++ b/src/hatch/project/core.py @@ -1,10 +1,13 @@ from __future__ import annotations import re +from typing import TYPE_CHECKING -from hatch.config.model import RootConfig from hatch.utils.fs import Path +if TYPE_CHECKING: + from hatch.config.model import RootConfig + class Project: def __init__(self, path: Path, *, name: str | None = None, config=None): @@ -72,6 +75,8 @@ def from_config(cls, config: RootConfig, project: str) -> Project | None: if location.is_dir(): return cls(Path(location).resolve(), name=project) + return None + def find_project_root(self) -> Path | None: path = self._path @@ -80,7 +85,8 @@ def find_project_root(self) -> Path | None: if possible_file.is_file(): self._project_file_path = possible_file return path - elif path.joinpath('setup.py').is_file(): + + if path.joinpath('setup.py').is_file(): return path new_path = path.parent @@ -93,9 +99,9 @@ def find_project_root(self) -> Path | None: def canonicalize_name(name: str, *, strict=True) -> str: if strict: return re.sub(r'[-_.]+', '-', name).lower() - else: - # Used for creating new projects - return re.sub(r'[-_. ]+', '-', name).lower() + + # Used for creating new projects + return re.sub(r'[-_. ]+', '-', name).lower() @property def metadata(self): diff --git a/src/hatch/project/env.py b/src/hatch/project/env.py index aee93cce9..6a75ca2cc 100644 --- a/src/hatch/project/env.py +++ b/src/hatch/project/env.py @@ -25,8 +25,8 @@ def apply_overrides(env_name, source, condition, condition_value, options, new_c if option_types is None: option_types = RESERVED_OPTIONS - for option, data in options.items(): - _, separator, option = option.rpartition('set-') + for raw_option, data in options.items(): + _, separator, option = raw_option.rpartition('set-') overwrite = bool(separator) # Prevent manipulation of reserved options @@ -77,12 +77,14 @@ def _apply_override_to_mapping(env_name, option, data, source, condition, condit f'{condition}.{option}` must be a string' ) raise TypeError(message) - elif not key: + + if not key: message = ( f'Option `key` in entry #{i} in field `tool.hatch.envs.{env_name}.overrides.{source}.' f'{condition}.{option}` cannot be an empty string' ) raise ValueError(message) + value = entry.get('value', condition_value) if not isinstance(value, str): message = ( @@ -135,7 +137,8 @@ def _apply_override_to_array(env_name, option, data, source, condition, conditio f'{condition}.{option}` must be a string' ) raise TypeError(message) - elif not value: + + if not value: message = ( f'Option `value` in entry #{i} in field `tool.hatch.envs.{env_name}.overrides.{source}.' f'{condition}.{option}` cannot be an empty string' @@ -191,7 +194,8 @@ def _apply_override_to_string( if isinstance(entry, str): new_config[option] = entry break - elif isinstance(entry, dict): + + if isinstance(entry, dict): if 'value' not in entry: message = ( f'Entry #{i} in field `tool.hatch.envs.{env_name}.overrides.{source}.{condition}.{option}` ' @@ -255,7 +259,8 @@ def _apply_override_to_boolean( if isinstance(entry, bool): new_config[option] = entry break - elif isinstance(entry, dict): + + if isinstance(entry, dict): if 'value' not in entry: message = ( f'Entry #{i} in field `tool.hatch.envs.{env_name}.overrides.{source}.{condition}.{option}` ' diff --git a/src/hatch/project/utils.py b/src/hatch/project/utils.py index 641c4edfd..a72125de0 100644 --- a/src/hatch/project/utils.py +++ b/src/hatch/project/utils.py @@ -12,8 +12,8 @@ def parse_script_command(command): def format_script_commands(commands, args, ignore_exit_code): for command in commands: if args: - command = f'{command} {args}' - if ignore_exit_code and not command.startswith('- '): - command = f'- {command}' - - yield command + yield f'{command} {args}' + elif ignore_exit_code and not command.startswith('- '): + yield f'- {command}' + else: + yield command diff --git a/src/hatch/publish/index.py b/src/hatch/publish/index.py index 99d52f04d..98eedda56 100644 --- a/src/hatch/publish/index.py +++ b/src/hatch/publish/index.py @@ -20,13 +20,13 @@ def get_repos(self): repos = {} for repo, data in defined_repos.items(): if isinstance(data, str): - data = {'url': data} + repos[repo] = {'url': data} elif not isinstance(data, dict): self.app.abort(f'Hatch config field `publish.index.repos.{repo}` must be a string or a mapping') elif 'url' not in data: self.app.abort(f'Hatch config field `publish.index.repos.{repo}` must define a `url` key') - - repos[repo] = data + else: + repos[repo] = data # Ensure PyPI correct for repo, url in (('main', 'https://upload.pypi.org/legacy/'), ('test', 'https://test.pypi.org/legacy/')): @@ -129,7 +129,7 @@ def publish(self, artifacts: list, options: dict): try: response = index.get_simple_api(project_name) response.raise_for_status() - except Exception: # no cov + except Exception: # no cov # noqa: BLE001 existing_artifacts[project_name] = set() else: existing_artifacts[project_name] = set(parse_artifacts(response.text)) @@ -140,7 +140,7 @@ def publish(self, artifacts: list, options: dict): try: index.upload_artifact(artifact, data) - except Exception as e: + except Exception as e: # noqa: BLE001 self.app.display_error('failed') self.app.abort(f'Error uploading to repository: {index.repo} - {e}'.replace(index.auth, '*****')) else: @@ -171,8 +171,8 @@ def publish(self, artifacts: list, options: dict): def recurse_artifacts(artifacts: list, root) -> Iterable[Path]: - for artifact in artifacts: - artifact = Path(artifact) + for raw_artifact in artifacts: + artifact = Path(raw_artifact) if not artifact.is_absolute(): artifact = root / artifact diff --git a/src/hatch/python/core.py b/src/hatch/python/core.py index b69aa9e1f..b0914b7db 100644 --- a/src/hatch/python/core.py +++ b/src/hatch/python/core.py @@ -121,5 +121,6 @@ def install(self, identifier: str) -> InstalledDistribution: return InstalledDistribution(path, dist, metadata) - def remove(self, dist: InstalledDistribution) -> None: + @staticmethod + def remove(dist: InstalledDistribution) -> None: dist.path.wait_for_dir_removed() diff --git a/src/hatch/python/resolve.py b/src/hatch/python/resolve.py index b91be9dc1..dc8f1d530 100644 --- a/src/hatch/python/resolve.py +++ b/src/hatch/python/resolve.py @@ -91,12 +91,13 @@ def python_path(self) -> str: if self.name == '3.7': if sys.platform == 'win32': return r'python\install\python.exe' - else: - return 'python/install/bin/python3' - elif sys.platform == 'win32': + + return 'python/install/bin/python3' + + if sys.platform == 'win32': return r'python\python.exe' - else: - return 'python/bin/python3' + + return 'python/bin/python3' class PyPyOfficialDistribution(Distribution): @@ -118,14 +119,15 @@ def python_path(self) -> str: if sys.platform == 'win32': return rf'{directory}\pypy.exe' - else: - return f'{directory}/bin/pypy' + + return f'{directory}/bin/pypy' def get_distribution(name: str, source: str = '', variant: str = '') -> Distribution: if source: return _get_distribution_class(source)(name, source) - elif name not in DISTRIBUTIONS: + + if name not in DISTRIBUTIONS: message = f'Unknown distribution: {name}' raise PythonDistributionUnknownError(message) @@ -175,10 +177,12 @@ def _get_default_variant(name: str, system: str, arch: str, abi: str) -> str: if name[0].isdigit(): if system == 'windows' and abi == 'msvc': return 'shared' - elif system == 'linux' and arch == 'x86_64': + + if system == 'linux' and arch == 'x86_64': if name == '3.8': return 'v1' - elif name != '3.7': + + if name != '3.7': return 'v3' return '' @@ -187,8 +191,9 @@ def _get_default_variant(name: str, system: str, arch: str, abi: str) -> str: def _get_distribution_class(source: str) -> type[Distribution]: if source.startswith('https://github.com/indygreg/python-build-standalone/releases/download/'): return CPythonStandaloneDistribution - elif source.startswith('https://downloads.python.org/pypy/'): + + if source.startswith('https://downloads.python.org/pypy/'): return PyPyOfficialDistribution - else: - message = f'Unknown distribution source: {source}' - raise ValueError(message) + + message = f'Unknown distribution source: {source}' + raise ValueError(message) diff --git a/src/hatch/template/__init__.py b/src/hatch/template/__init__.py index 3ac60543c..d1008812a 100644 --- a/src/hatch/template/__init__.py +++ b/src/hatch/template/__init__.py @@ -1,11 +1,14 @@ +from __future__ import annotations + from contextlib import suppress -from typing import Optional +from typing import TYPE_CHECKING -from hatch.utils.fs import Path +if TYPE_CHECKING: + from hatch.utils.fs import Path class File: - def __init__(self, path: Optional[Path], contents: str = ''): + def __init__(self, path: Path | None, contents: str = ''): self.path = path self.contents = contents self.feature = None diff --git a/src/hatch/template/default.py b/src/hatch/template/default.py index 3e3c940cc..7463a2d80 100644 --- a/src/hatch/template/default.py +++ b/src/hatch/template/default.py @@ -44,7 +44,7 @@ def initialize_config(self, config): for _ in range(5): try: download_file(cached_license_path, url, timeout=2) - except Exception: # noqa: S112 + except Exception: # noqa: BLE001, S112 continue else: break @@ -80,7 +80,7 @@ def get_files(self, config): license_data = config['license_data'] if license_data: if len(license_data) == 1: - license_id, text = list(license_data.items())[0] + license_id, text = next(iter(license_data.items())) license_text = get_license_text(config, license_id, text, self.creation_time) files.append(File(Path('LICENSE.txt'), license_text)) else: diff --git a/src/hatch/template/files_default.py b/src/hatch/template/files_default.py index 562931662..ebe86ae85 100644 --- a/src/hatch/template/files_default.py +++ b/src/hatch/template/files_default.py @@ -57,7 +57,7 @@ def __init__( license_data = template_config['license_data'] if len(license_data) == 1: - license_id = list(license_data)[0] + license_id = next(iter(license_data)) license_info += f'the [{license_id}](https://spdx.org/licenses/{license_id}.html) license.' else: license_info += 'any of the following licenses:\n' @@ -124,9 +124,8 @@ def __init__(self, template_config: dict, plugin_config: dict): ) if project_urls: for label, url in project_urls.items(): - if ' ' in label: - label = f'"{label}"' - project_url_data += f'\n{label} = "{url.format(**template_config)}"' + normalized_label = f'"{label}"' if ' ' in label else label + project_url_data += f'\n{normalized_label} = "{url.format(**template_config)}"' dependency_data = '[' if template_config['dependencies']: diff --git a/src/hatch/template/plugin/interface.py b/src/hatch/template/plugin/interface.py index 361bfb1d1..2a361c666 100644 --- a/src/hatch/template/plugin/interface.py +++ b/src/hatch/template/plugin/interface.py @@ -13,7 +13,7 @@ def initialize_config(self, config): before the list of files are determined. """ - def get_files(self, config): # noqa: ARG002 + def get_files(self, config): # noqa: ARG002, PLR6301 """Add to the list of files for new projects that are written to the file system.""" return [] diff --git a/src/hatch/utils/dep.py b/src/hatch/utils/dep.py index a5c491d82..5027f02e7 100644 --- a/src/hatch/utils/dep.py +++ b/src/hatch/utils/dep.py @@ -50,7 +50,7 @@ def get_project_dependencies_complex( else: try: environment.check_compatibility() - except Exception as e: + except Exception as e: # noqa: BLE001 environment.app.abort(f'Environment `{environment.name}` is incompatible: {e}') import json diff --git a/src/hatch/utils/platform.py b/src/hatch/utils/platform.py index fa57162f7..beb2a280b 100644 --- a/src/hatch/utils/platform.py +++ b/src/hatch/utils/platform.py @@ -70,7 +70,8 @@ def format_for_subprocess(self, command: str | list[str], *, shell: bool) -> str return command - def exit_with_code(self, code: str | int | None) -> None: + @staticmethod + def exit_with_code(code: str | int | None) -> None: sys.exit(code) def _run_command_integrated( @@ -241,7 +242,7 @@ def exit_with_command(self, command: list[str]) -> None: process = self.run_command(command) self.exit_with_code(process.returncode) else: - os.execvp(command[0], command) + os.execvp(command[0], command) # noqa: S606 @property def name(self) -> str: diff --git a/tests/backend/builders/test_app.py b/tests/backend/builders/test_app.py index 565906a38..4d53b8e92 100644 --- a/tests/backend/builders/test_app.py +++ b/tests/backend/builders/test_app.py @@ -20,6 +20,9 @@ def __init__(self, env_vars: dict): def __eq__(self, other): return all(not (key not in other or other[key] != value) for key, value in self.env_vars.items()) + def __hash__(self): + return hash(self.env_vars) + def cargo_install(*args: Any, **_kwargs: Any) -> subprocess.CompletedProcess: executable_name = 'pyapp.exe' if sys.platform == 'win32' else 'pyapp' diff --git a/tests/backend/builders/test_wheel.py b/tests/backend/builders/test_wheel.py index c4e1c7e89..967b81428 100644 --- a/tests/backend/builders/test_wheel.py +++ b/tests/backend/builders/test_wheel.py @@ -2883,7 +2883,7 @@ def test_editable_sources_rewrite_error(self, hatch, temp_dir): reason='requires support for ARM on macOS', ) @pytest.mark.parametrize( - 'archflags, expected_arch', + ('archflags', 'expected_arch'), [('-arch x86_64', 'x86_64'), ('-arch arm64', 'arm64'), ('-arch arm64 -arch x86_64', 'universal2')], ) def test_macos_archflags(self, hatch, helpers, temp_dir, config_file, archflags, expected_arch): diff --git a/tests/backend/licenses/test_parse.py b/tests/backend/licenses/test_parse.py index 81ebc972d..9480a7c37 100644 --- a/tests/backend/licenses/test_parse.py +++ b/tests/backend/licenses/test_parse.py @@ -39,7 +39,7 @@ def test_unknown_license_exception(): @pytest.mark.parametrize( - 'raw, normalized', + ('raw', 'normalized'), [ ('mIt', 'MIT'), ('mit or apache-2.0', 'MIT OR Apache-2.0'), diff --git a/tests/backend/metadata/test_core.py b/tests/backend/metadata/test_core.py index b0134e8a9..0096f30a0 100644 --- a/tests/backend/metadata/test_core.py +++ b/tests/backend/metadata/test_core.py @@ -32,13 +32,8 @@ class TestInterface: def test_types(self, isolation): metadata = ProjectMetadata(str(isolation), None, {'project': {}}) - assert metadata.core is metadata._core assert isinstance(metadata.core, CoreMetadata) - - assert metadata.hatch is metadata._hatch assert isinstance(metadata.hatch, HatchMetadata) - - assert metadata.build is metadata._build assert isinstance(metadata.build, BuildMetadata) def test_missing_core_metadata(self, isolation): @@ -383,7 +378,7 @@ def test_string_path_nonexistent(self, isolation): _ = metadata.core.readme @pytest.mark.parametrize( - 'extension, content_type', [('.md', 'text/markdown'), ('.rst', 'text/x-rst'), ('.txt', 'text/plain')] + ('extension', 'content_type'), [('.md', 'text/markdown'), ('.rst', 'text/x-rst'), ('.txt', 'text/plain')] ) def test_string_correct(self, extension, content_type, temp_dir): metadata = ProjectMetadata(str(temp_dir), None, {'project': {'readme': f'foo/bar{extension}'}}) diff --git a/tests/backend/version/scheme/test_standard.py b/tests/backend/version/scheme/test_standard.py index e36c46b0f..b053186ed 100644 --- a/tests/backend/version/scheme/test_standard.py +++ b/tests/backend/version/scheme/test_standard.py @@ -106,7 +106,7 @@ def test_explicit_error(self, isolation): scheme.update('5,rc', '3', {}) @pytest.mark.parametrize( - 'operations, expected', + ('operations', 'expected'), [ ('fix,rc', '0.0.2rc0'), ('minor,dev', '0.1.0.dev0'), diff --git a/tests/backend/version/source/test_regex.py b/tests/backend/version/source/test_regex.py index 744589b61..9eecf3be2 100644 --- a/tests/backend/version/source/test_regex.py +++ b/tests/backend/version/source/test_regex.py @@ -72,7 +72,7 @@ def test_match_custom_pattern(temp_dir): assert source.get_version_data()['version'] == '0.0.1' -@pytest.mark.parametrize('variable, quote, prefix', DEFAULT_PATTERN_PRODUCTS) +@pytest.mark.parametrize(('variable', 'quote', 'prefix'), DEFAULT_PATTERN_PRODUCTS) def test_match_default_pattern(temp_dir, helpers, variable, quote, prefix): source = RegexSource(str(temp_dir), {'path': 'a/b'}) @@ -95,7 +95,7 @@ def foo(): assert source.get_version_data()['version'] == '0.0.1' -@pytest.mark.parametrize('variable, quote, prefix', DEFAULT_PATTERN_PRODUCTS) +@pytest.mark.parametrize(('variable', 'quote', 'prefix'), DEFAULT_PATTERN_PRODUCTS) def test_set_default_pattern(temp_dir, helpers, variable, quote, prefix): source = RegexSource(str(temp_dir), {'path': 'a/b'}) diff --git a/tests/cli/dep/show/test_table.py b/tests/cli/dep/show/test_table.py index a695370af..027f9def0 100644 --- a/tests/cli/dep/show/test_table.py +++ b/tests/cli/dep/show/test_table.py @@ -8,7 +8,7 @@ @pytest.fixture(scope='module', autouse=True) -def terminal_width(): +def _terminal_width(): with EnvVars({'COLUMNS': '200'}): yield diff --git a/tests/cli/env/test_show.py b/tests/cli/env/test_show.py index 9cc2f42a2..ad43d8c81 100644 --- a/tests/cli/env/test_show.py +++ b/tests/cli/env/test_show.py @@ -8,7 +8,7 @@ @pytest.fixture(scope='module', autouse=True) -def terminal_width(): +def _terminal_width(): with EnvVars({'COLUMNS': '200'}): yield diff --git a/tests/cli/publish/test_publish.py b/tests/cli/publish/test_publish.py index 650bec1fd..c27a4bd0a 100644 --- a/tests/cli/publish/test_publish.py +++ b/tests/cli/publish/test_publish.py @@ -48,8 +48,8 @@ def timestamp_to_version(timestamp): normalized_minor = str(int(minor)) padding = '.'.join('0' for _ in range(len(minor) - len(normalized_minor))) return f'{major}.{padding}.{normalized_minor}' - else: - return f'{major}.{minor}' + + return f'{major}.{minor}' def test_timestamp_to_version(): diff --git a/tests/cli/python/conftest.py b/tests/cli/python/conftest.py index 25a11719e..7a783b19a 100644 --- a/tests/cli/python/conftest.py +++ b/tests/cli/python/conftest.py @@ -9,7 +9,7 @@ def default_shells(platform): @pytest.fixture(autouse=True) -def isolated_python_directory(config_file): +def isolated_python_directory(config_file): # noqa: PT004 config_file.model.dirs.python = 'isolated' config_file.save() @@ -20,7 +20,7 @@ def path_append(mocker): @pytest.fixture(autouse=True) -def disable_path_detectors(mocker): +def disable_path_detectors(mocker): # noqa: PT004 mocker.patch('userpath.in_current_path', return_value=False) mocker.patch('userpath.in_new_path', return_value=False) diff --git a/tests/cli/python/test_install.py b/tests/cli/python/test_install.py index 585852866..2bb79d8ae 100644 --- a/tests/cli/python/test_install.py +++ b/tests/cli/python/test_install.py @@ -272,15 +272,16 @@ def test_all(hatch, temp_dir_data, path_append, default_shells, mocker, compatib expected_lines = [] for dist in mocked_dists: - expected_lines.append(f'Installing {dist.path.name}') - expected_lines.append(f'Installed {dist.path.name} @ {dist.path}') - - expected_lines.append('') - expected_lines.append('The following directories have been added to your PATH (pending a shell restart):') - expected_lines.append('') - - for dist in mocked_dists: - expected_lines.append(str(dist.python_path.parent)) + expected_lines.extend((f'Installing {dist.path.name}', f'Installed {dist.path.name} @ {dist.path}')) + + expected_lines.extend( + ( + '', + 'The following directories have been added to your PATH (pending a shell restart):', + '', + ) + ) + expected_lines.extend(str(dist.python_path.parent) for dist in mocked_dists) expected_lines.append('') assert result.output == '\n'.join(expected_lines) diff --git a/tests/cli/python/test_remove.py b/tests/cli/python/test_remove.py index f2dabb090..ea1ca2248 100644 --- a/tests/cli/python/test_remove.py +++ b/tests/cli/python/test_remove.py @@ -54,9 +54,7 @@ def test_all(hatch, helpers, temp_dir_data): assert result.exit_code == 0, result.output - expected_lines = [] - for name in installed_distributions: - expected_lines.append(f'Removing {name}') + expected_lines = [f'Removing {name}' for name in installed_distributions] expected_lines.append('') assert result.output == '\n'.join(expected_lines) diff --git a/tests/cli/python/test_update.py b/tests/cli/python/test_update.py index f84398e5a..15fa7337b 100644 --- a/tests/cli/python/test_update.py +++ b/tests/cli/python/test_update.py @@ -81,8 +81,7 @@ def test_all(hatch, helpers, temp_dir_data, path_append, mocker): expected_lines = [] for dist in mocked_dists: - expected_lines.append(f'Updating {dist.path.name}') - expected_lines.append(f'Updated {dist.path.name} @ {dist.path}') + expected_lines.extend((f'Updating {dist.path.name}', f'Updated {dist.path.name} @ {dist.path}')) expected_lines.append('') assert result.output == '\n'.join(expected_lines) diff --git a/tests/conftest.py b/tests/conftest.py index 3b8097d22..b17db4179 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,10 +4,10 @@ import subprocess import sys import time -from collections import namedtuple +from contextlib import suppress from functools import lru_cache from io import BytesIO -from typing import Generator +from typing import Generator, NamedTuple import pytest from click.testing import CliRunner as __CliRunner @@ -26,7 +26,14 @@ from .helpers.templates.licenses import MIT, Apache_2_0 PLATFORM = Platform() -DEVPI = namedtuple('DEVPI', ('repo', 'index', 'user', 'auth', 'ca_cert')) + + +class Devpi(NamedTuple): + repo: str + index_name: str + user: str + auth: str + ca_cert: str class CliRunner(__CliRunner): @@ -240,8 +247,8 @@ def devpi(tmp_path_factory, worker_id): data = {'password': os.urandom(16).hex(), 'ca_cert': client_cert} devpi_data_file.write_atomic(json.dumps(data), 'w', encoding='utf-8') - dp = DEVPI('https://localhost:8443/hatch/testing/', 'testing', 'hatch', data['password'], data['ca_cert']) - env_vars = {'DEVPI_INDEX_NAME': dp.index, 'DEVPI_USERNAME': dp.user, 'DEVPI_PASSWORD': dp.auth} + dp = Devpi('https://localhost:8443/hatch/testing/', 'testing', 'hatch', data['password'], data['ca_cert']) + env_vars = {'DEVPI_INDEX_NAME': dp.index_name, 'DEVPI_USERNAME': dp.user, 'DEVPI_PASSWORD': dp.auth} compose_file = str(devpi_docker_data / 'docker-compose.yaml') with FileLock(lock_file): @@ -251,7 +258,7 @@ def devpi(tmp_path_factory, worker_id): for _ in range(60): output = subprocess.check_output(['docker', 'logs', 'hatch-devpi']).decode('utf-8') - if f'Serving index {dp.user}/{dp.index}' in output: + if f'Serving index {dp.user}/{dp.index_name}' in output: time.sleep(5) break @@ -272,7 +279,7 @@ def devpi(tmp_path_factory, worker_id): shutil.rmtree(devpi_ended_sessions) with EnvVars(env_vars): - subprocess.run(['docker', 'compose', '-f', compose_file, 'down', '-t', '0'], capture_output=True) + subprocess.run(['docker', 'compose', '-f', compose_file, 'down', '-t', '0'], capture_output=True) # noqa: PLW1510 shutil.rmtree(devpi_data) @@ -341,6 +348,8 @@ def local_builder(mock_backend_process, mocker): if mock_backend_process: mocker.patch('hatch.env.virtual.VirtualEnvironment.build_environment') + return mock_backend_process + def pytest_runtest_setup(item): for marker in item.iter_markers(): @@ -387,12 +396,11 @@ def network_connectivity(): # no cov import socket - try: + with suppress(Exception): # Test availability of DNS first host = socket.gethostbyname('www.google.com') # Test connection socket.create_connection((host, 80), 2) - except Exception: - return False + return True - return True + return False diff --git a/tests/env/plugin/test_interface.py b/tests/env/plugin/test_interface.py index 07566bb17..d2a7eabda 100644 --- a/tests/env/plugin/test_interface.py +++ b/tests/env/plugin/test_interface.py @@ -1617,8 +1617,8 @@ def test_verbosity_flag_adjustment_not_integer(self, isolation, isolated_data_di next(environment.expand_command('foo')) @pytest.mark.parametrize( - 'verbosity, command', - ( + ('verbosity', 'command'), + [ (-9000, 'command -qqq'), (-3, 'command -qqq'), (-2, 'command -qq'), @@ -1628,7 +1628,7 @@ def test_verbosity_flag_adjustment_not_integer(self, isolation, isolated_data_di (2, 'command -vv'), (3, 'command -vvv'), (9000, 'command -vvv'), - ), + ], ) def test_verbosity_flag_default(self, isolation, isolated_data_dir, platform, verbosity, command): config = { @@ -1651,8 +1651,8 @@ def test_verbosity_flag_default(self, isolation, isolated_data_dir, platform, ve assert list(environment.expand_command('foo')) == [command] @pytest.mark.parametrize( - 'adjustment, command', - ( + ('adjustment', 'command'), + [ (-9000, 'command -qqq'), (-3, 'command -qqq'), (-2, 'command -qq'), @@ -1662,7 +1662,7 @@ def test_verbosity_flag_default(self, isolation, isolated_data_dir, platform, ve (2, 'command -vv'), (3, 'command -vvv'), (9000, 'command -vvv'), - ), + ], ) def test_verbosity_flag_adjustment(self, isolation, isolated_data_dir, platform, adjustment, command): config = { diff --git a/tests/helpers/helpers.py b/tests/helpers/helpers.py index 710a80550..0e48fe6ce 100644 --- a/tests/helpers/helpers.py +++ b/tests/helpers/helpers.py @@ -30,8 +30,8 @@ def remove_trailing_spaces(text): def extract_requirements(lines): - for line in lines: - line = line.rstrip() + for raw_line in lines: + line = raw_line.rstrip() if line and not line.startswith('#'): yield line diff --git a/tests/helpers/templates/new/feature_ci.py b/tests/helpers/templates/new/feature_ci.py index 2ea4abd0b..bbd6f2da5 100644 --- a/tests/helpers/templates/new/feature_ci.py +++ b/tests/helpers/templates/new/feature_ci.py @@ -5,10 +5,7 @@ def get_files(**kwargs): - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(f.path), f.contents)) - + files = [File(Path(f.path), f.contents) for f in get_template_files(**kwargs)] files.append( File( Path('.github', 'workflows', 'test.yml'), diff --git a/tests/helpers/templates/sdist/standard_default.py b/tests/helpers/templates/sdist/standard_default.py index 7a8e67160..301275412 100644 --- a/tests/helpers/templates/sdist/standard_default.py +++ b/tests/helpers/templates/sdist/standard_default.py @@ -8,10 +8,7 @@ def get_files(**kwargs): relative_root = kwargs.get('relative_root', '') - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(relative_root, f.path), f.contents)) - + files = [File(Path(relative_root, f.path), f.contents) for f in get_template_files(**kwargs)] files.append( File( Path(relative_root, 'PKG-INFO'), diff --git a/tests/helpers/templates/sdist/standard_default_build_script_artifacts.py b/tests/helpers/templates/sdist/standard_default_build_script_artifacts.py index 3f64263c7..6ab50ad04 100644 --- a/tests/helpers/templates/sdist/standard_default_build_script_artifacts.py +++ b/tests/helpers/templates/sdist/standard_default_build_script_artifacts.py @@ -9,25 +9,21 @@ def get_files(**kwargs): relative_root = kwargs.get('relative_root', '') - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(relative_root, f.path), f.contents)) - - files.append(File(Path(relative_root, kwargs['package_name'], 'lib.so'), '')) - files.append( - File( - Path(relative_root, '.gitignore'), - """\ + files = [File(Path(relative_root, f.path), f.contents) for f in get_template_files(**kwargs)] + files.extend( + ( + File(Path(relative_root, kwargs['package_name'], 'lib.so'), ''), + File( + Path(relative_root, '.gitignore'), + """\ *.pyc *.so *.h """, - ) - ) - files.append( - File( - Path(relative_root, DEFAULT_BUILD_SCRIPT), - """\ + ), + File( + Path(relative_root, DEFAULT_BUILD_SCRIPT), + """\ import pathlib from hatchling.builders.hooks.plugin.interface import BuildHookInterface @@ -37,17 +33,16 @@ def initialize(self, version, build_data): pathlib.Path('my_app', 'lib.so').touch() pathlib.Path('my_app', 'lib.h').touch() """, - ) - ) - files.append( - File( - Path(relative_root, 'PKG-INFO'), - f"""\ + ), + File( + Path(relative_root, 'PKG-INFO'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/sdist/standard_default_build_script_extra_dependencies.py b/tests/helpers/templates/sdist/standard_default_build_script_extra_dependencies.py index 7758aeb7e..265ab604b 100644 --- a/tests/helpers/templates/sdist/standard_default_build_script_extra_dependencies.py +++ b/tests/helpers/templates/sdist/standard_default_build_script_extra_dependencies.py @@ -9,25 +9,21 @@ def get_files(**kwargs): relative_root = kwargs.get('relative_root', '') - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(relative_root, f.path), f.contents)) - - files.append(File(Path(relative_root, kwargs['package_name'], 'lib.so'), '')) - files.append( - File( - Path(relative_root, '.gitignore'), - """\ + files = [File(Path(relative_root, f.path), f.contents) for f in get_template_files(**kwargs)] + files.extend( + ( + File(Path(relative_root, kwargs['package_name'], 'lib.so'), ''), + File( + Path(relative_root, '.gitignore'), + """\ *.pyc *.so *.h """, - ) - ) - files.append( - File( - Path(relative_root, DEFAULT_BUILD_SCRIPT), - """\ + ), + File( + Path(relative_root, DEFAULT_BUILD_SCRIPT), + """\ import pathlib from hatchling.builders.hooks.plugin.interface import BuildHookInterface @@ -38,18 +34,17 @@ def initialize(self, version, build_data): pathlib.Path('my_app', 'lib.h').touch() build_data['dependencies'].append('binary') """, - ) - ) - files.append( - File( - Path(relative_root, 'PKG-INFO'), - f"""\ + ), + File( + Path(relative_root, 'PKG-INFO'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Dist: binary """, + ), ) ) diff --git a/tests/helpers/templates/sdist/standard_default_support_legacy.py b/tests/helpers/templates/sdist/standard_default_support_legacy.py index 9fa4a458b..1f5c8d92d 100644 --- a/tests/helpers/templates/sdist/standard_default_support_legacy.py +++ b/tests/helpers/templates/sdist/standard_default_support_legacy.py @@ -8,25 +8,21 @@ def get_files(**kwargs): relative_root = kwargs.get('relative_root', '') - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(relative_root, f.path), f.contents)) - - files.append( - File( - Path(relative_root, 'PKG-INFO'), - f"""\ + files = [File(Path(relative_root, f.path), f.contents) for f in get_template_files(**kwargs)] + files.extend( + ( + File( + Path(relative_root, 'PKG-INFO'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, - ) - ) - files.append( - File( - Path(relative_root, 'setup.py'), - f"""\ + ), + File( + Path(relative_root, 'setup.py'), + f"""\ # -*- coding: utf-8 -*- from setuptools import setup @@ -39,6 +35,7 @@ def get_files(**kwargs): ], ) """, + ), ) ) diff --git a/tests/helpers/templates/sdist/standard_default_vcs_git_exclusion_files.py b/tests/helpers/templates/sdist/standard_default_vcs_git_exclusion_files.py index 7739bfcdb..fd68cf971 100644 --- a/tests/helpers/templates/sdist/standard_default_vcs_git_exclusion_files.py +++ b/tests/helpers/templates/sdist/standard_default_vcs_git_exclusion_files.py @@ -8,30 +8,27 @@ def get_files(**kwargs): relative_root = kwargs.get('relative_root', '') - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(relative_root, f.path), f.contents)) - - files.append(File(Path(relative_root, kwargs['package_name'], 'lib.so'), '')) - files.append( - File( - Path(relative_root, '.gitignore'), - """\ + files = [File(Path(relative_root, f.path), f.contents) for f in get_template_files(**kwargs)] + files.extend( + ( + File(Path(relative_root, kwargs['package_name'], 'lib.so'), ''), + File( + Path(relative_root, '.gitignore'), + """\ *.pyc *.so *.h """, - ) - ) - files.append( - File( - Path(relative_root, 'PKG-INFO'), - f"""\ + ), + File( + Path(relative_root, 'PKG-INFO'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/sdist/standard_default_vcs_mercurial_exclusion_files.py b/tests/helpers/templates/sdist/standard_default_vcs_mercurial_exclusion_files.py index 8156eeddd..6cfb11afb 100644 --- a/tests/helpers/templates/sdist/standard_default_vcs_mercurial_exclusion_files.py +++ b/tests/helpers/templates/sdist/standard_default_vcs_mercurial_exclusion_files.py @@ -8,15 +8,13 @@ def get_files(**kwargs): relative_root = kwargs.get('relative_root', '') - files = [] - for f in get_template_files(**kwargs): - files.append(File(Path(relative_root, f.path), f.contents)) - - files.append(File(Path(relative_root, kwargs['package_name'], 'lib.so'), '')) - files.append( - File( - Path(relative_root, '.hgignore'), - """\ + files = [File(Path(relative_root, f.path), f.contents) for f in get_template_files(**kwargs)] + files.extend( + ( + File(Path(relative_root, kwargs['package_name'], 'lib.so'), ''), + File( + Path(relative_root, '.hgignore'), + """\ syntax: glob *.pyc @@ -27,17 +25,16 @@ def get_files(**kwargs): *.so *.h """, - ) - ) - files.append( - File( - Path(relative_root, 'PKG-INFO'), - f"""\ + ), + File( + Path(relative_root, 'PKG-INFO'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/sdist/standard_include.py b/tests/helpers/templates/sdist/standard_include.py index 7859c25e7..8bb9fa6dc 100644 --- a/tests/helpers/templates/sdist/standard_include.py +++ b/tests/helpers/templates/sdist/standard_include.py @@ -11,7 +11,7 @@ def get_files(**kwargs): files = [] for f in get_template_files(**kwargs): part = f.path.parts[0] - if part == 'my_app' or part == 'pyproject.toml' or part == 'README.md' or part == 'LICENSE.txt': + if part in ('my_app', 'pyproject.toml', 'README.md', 'LICENSE.txt'): files.append(File(Path(relative_root, f.path), f.contents)) files.append( diff --git a/tests/helpers/templates/sdist/standard_include_config_file.py b/tests/helpers/templates/sdist/standard_include_config_file.py index 4967391b6..2143fea2c 100644 --- a/tests/helpers/templates/sdist/standard_include_config_file.py +++ b/tests/helpers/templates/sdist/standard_include_config_file.py @@ -11,14 +11,15 @@ def get_files(**kwargs): files = [] for f in get_template_files(**kwargs): part = f.path.parts[0] - if part == 'my_app' or part == 'pyproject.toml' or part == 'README.md' or part == 'LICENSE.txt': + if part in ('my_app', 'pyproject.toml', 'README.md', 'LICENSE.txt'): files.append(File(Path(relative_root, f.path), f.contents)) - files.append(File(Path(relative_root, 'hatch.toml'), '')) - files.append( - File( - Path(relative_root, 'PKG-INFO'), - f"""\ + files.extend( + ( + File(Path(relative_root, 'hatch.toml'), ''), + File( + Path(relative_root, 'PKG-INFO'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 @@ -47,6 +48,7 @@ def get_files(**kwargs): `my-app` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license. """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_build_script.py b/tests/helpers/templates/wheel/standard_default_build_script.py index f14e85492..a027bb06a 100644 --- a/tests/helpers/templates/wheel/standard_default_build_script.py +++ b/tests/helpers/templates/wheel/standard_default_build_script.py @@ -20,27 +20,27 @@ def get_files(**kwargs): files.append(f) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_build_script_artifacts.py b/tests/helpers/templates/wheel/standard_default_build_script_artifacts.py index 73308c320..e1acf0efb 100644 --- a/tests/helpers/templates/wheel/standard_default_build_script_artifacts.py +++ b/tests/helpers/templates/wheel/standard_default_build_script_artifacts.py @@ -20,28 +20,28 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(kwargs['package_name'], 'lib.so'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(kwargs['package_name'], 'lib.so'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: false Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_build_script_artifacts_with_src_layout.py b/tests/helpers/templates/wheel/standard_default_build_script_artifacts_with_src_layout.py index b72bdb3e4..1c048ee0a 100644 --- a/tests/helpers/templates/wheel/standard_default_build_script_artifacts_with_src_layout.py +++ b/tests/helpers/templates/wheel/standard_default_build_script_artifacts_with_src_layout.py @@ -20,29 +20,29 @@ def get_files(**kwargs): files.append(File(Path(*f.path.parts[1:]), f.contents)) - files.append(File(Path(kwargs['package_name'], 'lib.so'), '')) - files.append(File(Path('zlib.pyd'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(kwargs['package_name'], 'lib.so'), ''), + File(Path('zlib.pyd'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: false Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_build_script_configured_build_hooks.py b/tests/helpers/templates/wheel/standard_default_build_script_configured_build_hooks.py index 3f6507ec3..323a28d61 100644 --- a/tests/helpers/templates/wheel/standard_default_build_script_configured_build_hooks.py +++ b/tests/helpers/templates/wheel/standard_default_build_script_configured_build_hooks.py @@ -20,28 +20,28 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(kwargs['package_name'], 'lib.so'), 'custom')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(kwargs['package_name'], 'lib.so'), 'custom'), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: false Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_build_script_extra_dependencies.py b/tests/helpers/templates/wheel/standard_default_build_script_extra_dependencies.py index 800750c46..ebfd23a1f 100644 --- a/tests/helpers/templates/wheel/standard_default_build_script_extra_dependencies.py +++ b/tests/helpers/templates/wheel/standard_default_build_script_extra_dependencies.py @@ -20,22 +20,21 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(kwargs['package_name'], 'lib.so'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(kwargs['package_name'], 'lib.so'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: false Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 @@ -43,6 +42,7 @@ def get_files(**kwargs): Requires-Python: >3 Requires-Dist: binary """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_build_script_force_include.py b/tests/helpers/templates/wheel/standard_default_build_script_force_include.py index 7dc775551..6df7d069b 100644 --- a/tests/helpers/templates/wheel/standard_default_build_script_force_include.py +++ b/tests/helpers/templates/wheel/standard_default_build_script_force_include.py @@ -20,29 +20,29 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(kwargs['package_name'], 'lib.so'), '')) - files.append(File(Path(kwargs['package_name'], 'lib.h'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(kwargs['package_name'], 'lib.so'), ''), + File(Path(kwargs['package_name'], 'lib.h'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: false Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_extra_metadata.py b/tests/helpers/templates/wheel/standard_default_extra_metadata.py index bfdef1b84..e62ec8c54 100644 --- a/tests/helpers/templates/wheel/standard_default_extra_metadata.py +++ b/tests/helpers/templates/wheel/standard_default_extra_metadata.py @@ -20,29 +20,29 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(metadata_directory, 'extra_metadata', 'foo.txt'), '')) - files.append(File(Path(metadata_directory, 'extra_metadata', 'nested', 'bar.txt'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(metadata_directory, 'extra_metadata', 'foo.txt'), ''), + File(Path(metadata_directory, 'extra_metadata', 'nested', 'bar.txt'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_license_multiple.py b/tests/helpers/templates/wheel/standard_default_license_multiple.py index d8af4ab88..3a4ef32a6 100644 --- a/tests/helpers/templates/wheel/standard_default_license_multiple.py +++ b/tests/helpers/templates/wheel/standard_default_license_multiple.py @@ -22,28 +22,28 @@ def get_files(**kwargs): files.append(File(Path(*f.path.parts[1:]), f.contents)) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSES/Apache-2.0.txt License-File: LICENSES/MIT.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_license_single.py b/tests/helpers/templates/wheel/standard_default_license_single.py index 95975897a..e9c3348b4 100644 --- a/tests/helpers/templates/wheel/standard_default_license_single.py +++ b/tests/helpers/templates/wheel/standard_default_license_single.py @@ -20,27 +20,27 @@ def get_files(**kwargs): files.append(File(Path(*f.path.parts[1:]), f.contents)) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_namespace_package.py b/tests/helpers/templates/wheel/standard_default_namespace_package.py index 8f7317607..ab16857e6 100644 --- a/tests/helpers/templates/wheel/standard_default_namespace_package.py +++ b/tests/helpers/templates/wheel/standard_default_namespace_package.py @@ -22,27 +22,27 @@ def get_files(**kwargs): f.path = Path(namespace_package, f.path) files.append(f) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_python_constraint.py b/tests/helpers/templates/wheel/standard_default_python_constraint.py index 013ceecca..849cd82a8 100644 --- a/tests/helpers/templates/wheel/standard_default_python_constraint.py +++ b/tests/helpers/templates/wheel/standard_default_python_constraint.py @@ -20,27 +20,27 @@ def get_files(**kwargs): files.append(f) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_shared_data.py b/tests/helpers/templates/wheel/standard_default_shared_data.py index c3f324af3..55ce97658 100644 --- a/tests/helpers/templates/wheel/standard_default_shared_data.py +++ b/tests/helpers/templates/wheel/standard_default_shared_data.py @@ -21,29 +21,29 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(shared_data_directory, 'data', 'foo.txt'), '')) - files.append(File(Path(shared_data_directory, 'data', 'nested', 'bar.txt'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(shared_data_directory, 'data', 'foo.txt'), ''), + File(Path(shared_data_directory, 'data', 'nested', 'bar.txt'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_single_module.py b/tests/helpers/templates/wheel/standard_default_single_module.py index 7cd7e65cb..50902352b 100644 --- a/tests/helpers/templates/wheel/standard_default_single_module.py +++ b/tests/helpers/templates/wheel/standard_default_single_module.py @@ -10,33 +10,34 @@ def get_files(**kwargs): metadata_directory = kwargs.get('metadata_directory', '') - files = [] - for f in get_template_files(**kwargs): - if str(f.path) == 'LICENSE.txt': - files.append(File(Path(metadata_directory, 'licenses', f.path), f.contents)) + files = [ + File(Path(metadata_directory, 'licenses', f.path), f.contents) + for f in get_template_files(**kwargs) + if str(f.path) == 'LICENSE.txt' + ] - files.append(File(Path('my_app.py'), '')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path('my_app.py'), ''), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_default_symlink.py b/tests/helpers/templates/wheel/standard_default_symlink.py index 311d8a229..51203c98c 100644 --- a/tests/helpers/templates/wheel/standard_default_symlink.py +++ b/tests/helpers/templates/wheel/standard_default_symlink.py @@ -20,28 +20,28 @@ def get_files(**kwargs): files.append(f) - files.append(File(Path(kwargs['package_name'], 'lib.so'), 'data')) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(kwargs['package_name'], 'lib.so'), 'data'), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: false Tag: {kwargs.get('tag', '')} """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Python: >3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_editable_exact.py b/tests/helpers/templates/wheel/standard_editable_exact.py index 7cd591d53..1598c6325 100644 --- a/tests/helpers/templates/wheel/standard_editable_exact.py +++ b/tests/helpers/templates/wheel/standard_editable_exact.py @@ -11,45 +11,44 @@ def get_files(**kwargs): metadata_directory = kwargs.get('metadata_directory', '') package_root = kwargs.get('package_root', '') - files = [] - for f in get_template_files(**kwargs): - if str(f.path) == 'LICENSE.txt': - files.append(File(Path(metadata_directory, 'licenses', f.path), f.contents)) + files = [ + File(Path(metadata_directory, 'licenses', f.path), f.contents) + for f in get_template_files(**kwargs) + if str(f.path) == 'LICENSE.txt' + ] pth_file_name = f"_{kwargs['package_name']}.pth" loader_file_name = f"_editable_impl_{kwargs['package_name']}.py" - files.append(File(Path(pth_file_name), f"import _editable_impl_{kwargs['package_name']}")) - files.append( - File( - Path(loader_file_name), - f"""\ + files.extend( + ( + File(Path(pth_file_name), f"import _editable_impl_{kwargs['package_name']}"), + File( + Path(loader_file_name), + f"""\ from editables.redirector import RedirectingFinder as F F.install() F.map_module({kwargs['package_name']!r}, {package_root!r})""", - ) - ) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + ), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Dist: editables~=0.3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_editable_exact_extra_dependencies.py b/tests/helpers/templates/wheel/standard_editable_exact_extra_dependencies.py index a16eaf746..d49a37fa2 100644 --- a/tests/helpers/templates/wheel/standard_editable_exact_extra_dependencies.py +++ b/tests/helpers/templates/wheel/standard_editable_exact_extra_dependencies.py @@ -11,39 +11,37 @@ def get_files(**kwargs): metadata_directory = kwargs.get('metadata_directory', '') package_root = kwargs.get('package_root', '') - files = [] - for f in get_template_files(**kwargs): - if str(f.path) == 'LICENSE.txt': - files.append(File(Path(metadata_directory, 'licenses', f.path), f.contents)) + files = [ + File(Path(metadata_directory, 'licenses', f.path), f.contents) + for f in get_template_files(**kwargs) + if str(f.path) == 'LICENSE.txt' + ] pth_file_name = f"_{kwargs['package_name']}.pth" loader_file_name = f"_editable_impl_{kwargs['package_name']}.py" - files.append(File(Path(pth_file_name), f"import _editable_impl_{kwargs['package_name']}")) - files.append( - File( - Path(loader_file_name), - f"""\ + files.extend( + ( + File(Path(pth_file_name), f"import _editable_impl_{kwargs['package_name']}"), + File( + Path(loader_file_name), + f"""\ from editables.redirector import RedirectingFinder as F F.install() F.map_module({kwargs['package_name']!r}, {package_root!r})""", - ) - ) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + ), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 @@ -51,6 +49,7 @@ def get_files(**kwargs): Requires-Dist: binary Requires-Dist: editables~=0.3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_editable_exact_force_include.py b/tests/helpers/templates/wheel/standard_editable_exact_force_include.py index 60062da22..5b4e15538 100644 --- a/tests/helpers/templates/wheel/standard_editable_exact_force_include.py +++ b/tests/helpers/templates/wheel/standard_editable_exact_force_include.py @@ -20,38 +20,36 @@ def get_files(**kwargs): pth_file_name = f"_{kwargs['package_name']}.pth" loader_file_name = f"_editable_impl_{kwargs['package_name']}.py" - files.append(File(Path(pth_file_name), f"import _editable_impl_{kwargs['package_name']}")) - files.append( - File( - Path(loader_file_name), - f"""\ + files.extend( + ( + File(Path(pth_file_name), f"import _editable_impl_{kwargs['package_name']}"), + File( + Path(loader_file_name), + f"""\ from editables.redirector import RedirectingFinder as F F.install() F.map_module({kwargs['package_name']!r}, {package_root!r})""", - ) - ) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + ), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Dist: editables~=0.3 """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_editable_pth.py b/tests/helpers/templates/wheel/standard_editable_pth.py index 028d7a698..5aaf6a8f6 100644 --- a/tests/helpers/templates/wheel/standard_editable_pth.py +++ b/tests/helpers/templates/wheel/standard_editable_pth.py @@ -11,34 +11,35 @@ def get_files(**kwargs): metadata_directory = kwargs.get('metadata_directory', '') package_paths = kwargs.get('package_paths', []) - files = [] - for f in get_template_files(**kwargs): - if str(f.path) == 'LICENSE.txt': - files.append(File(Path(metadata_directory, 'licenses', f.path), f.contents)) + files = [ + File(Path(metadata_directory, 'licenses', f.path), f.contents) + for f in get_template_files(**kwargs) + if str(f.path) == 'LICENSE.txt' + ] pth_file_name = f"_{kwargs['package_name']}.pth" - files.append(File(Path(pth_file_name), '\n'.join(package_paths))) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(pth_file_name), '\n'.join(package_paths)), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_editable_pth_extra_dependencies.py b/tests/helpers/templates/wheel/standard_editable_pth_extra_dependencies.py index 746a86dfa..62f51b6c3 100644 --- a/tests/helpers/templates/wheel/standard_editable_pth_extra_dependencies.py +++ b/tests/helpers/templates/wheel/standard_editable_pth_extra_dependencies.py @@ -11,35 +11,36 @@ def get_files(**kwargs): metadata_directory = kwargs.get('metadata_directory', '') package_paths = kwargs.get('package_paths', []) - files = [] - for f in get_template_files(**kwargs): - if str(f.path) == 'LICENSE.txt': - files.append(File(Path(metadata_directory, 'licenses', f.path), f.contents)) + files = [ + File(Path(metadata_directory, 'licenses', f.path), f.contents) + for f in get_template_files(**kwargs) + if str(f.path) == 'LICENSE.txt' + ] pth_file_name = f"_{kwargs['package_name']}.pth" - files.append(File(Path(pth_file_name), '\n'.join(package_paths))) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(pth_file_name), '\n'.join(package_paths)), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt Requires-Dist: binary """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_editable_pth_force_include.py b/tests/helpers/templates/wheel/standard_editable_pth_force_include.py index 40e840e07..d158f858c 100644 --- a/tests/helpers/templates/wheel/standard_editable_pth_force_include.py +++ b/tests/helpers/templates/wheel/standard_editable_pth_force_include.py @@ -19,28 +19,28 @@ def get_files(**kwargs): files.append(File(Path('zfoo.py'), f.contents)) pth_file_name = f"_{kwargs['package_name']}.pth" - files.append(File(Path(pth_file_name), '\n'.join(package_paths))) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File(Path(pth_file_name), '\n'.join(package_paths)), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_entry_points.py b/tests/helpers/templates/wheel/standard_entry_points.py index dded899f8..e26197316 100644 --- a/tests/helpers/templates/wheel/standard_entry_points.py +++ b/tests/helpers/templates/wheel/standard_entry_points.py @@ -20,37 +20,35 @@ def get_files(**kwargs): files.append(f) - files.append( - File( - Path(metadata_directory, 'entry_points.txt'), - """\ + files.extend( + ( + File( + Path(metadata_directory, 'entry_points.txt'), + """\ [console_scripts] bar = pkg:foo foo = pkg:bar """, - ) - ) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + ), + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_no_strict_naming.py b/tests/helpers/templates/wheel/standard_no_strict_naming.py index 38de1c757..8b71c1301 100644 --- a/tests/helpers/templates/wheel/standard_no_strict_naming.py +++ b/tests/helpers/templates/wheel/standard_no_strict_naming.py @@ -20,27 +20,27 @@ def get_files(**kwargs): files.append(f) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_only_packages_artifact_override.py b/tests/helpers/templates/wheel/standard_only_packages_artifact_override.py index 7413266a8..50ea893c7 100644 --- a/tests/helpers/templates/wheel/standard_only_packages_artifact_override.py +++ b/tests/helpers/templates/wheel/standard_only_packages_artifact_override.py @@ -17,32 +17,33 @@ def get_files(**kwargs): if f.path.parts[0] not in (kwargs['package_name'], 'tests'): continue - elif f.path == Path('tests', '__init__.py'): + + if f.path == Path('tests', '__init__.py'): f.path = Path('tests', 'foo.py') files.append(f) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/helpers/templates/wheel/standard_tests.py b/tests/helpers/templates/wheel/standard_tests.py index 64b35b6da..ea015e4a0 100644 --- a/tests/helpers/templates/wheel/standard_tests.py +++ b/tests/helpers/templates/wheel/standard_tests.py @@ -20,27 +20,27 @@ def get_files(**kwargs): files.append(f) - files.append( - File( - Path(metadata_directory, 'WHEEL'), - f"""\ + files.extend( + ( + File( + Path(metadata_directory, 'WHEEL'), + f"""\ Wheel-Version: 1.0 Generator: hatchling {__version__} Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any """, - ) - ) - files.append( - File( - Path(metadata_directory, 'METADATA'), - f"""\ + ), + File( + Path(metadata_directory, 'METADATA'), + f"""\ Metadata-Version: {DEFAULT_METADATA_VERSION} Name: {kwargs['project_name']} Version: 0.0.1 License-File: LICENSE.txt """, + ), ) ) diff --git a/tests/index/test_core.py b/tests/index/test_core.py index 4baee02ba..20cda4280 100644 --- a/tests/index/test_core.py +++ b/tests/index/test_core.py @@ -12,7 +12,7 @@ def test_normalization(self): class TestURLs: @pytest.mark.parametrize( - 'repo_url, expected_url', + ('repo_url', 'expected_url'), [ pytest.param('https://upload.pypi.org/legacy/', 'https://pypi.org/simple/', id='PyPI main'), pytest.param('https://test.pypi.org/legacy/', 'https://test.pypi.org/simple/', id='PyPI test'), @@ -25,7 +25,7 @@ def test_simple(self, repo_url, expected_url): assert str(index.urls.simple) == expected_url @pytest.mark.parametrize( - 'repo_url, expected_url', + ('repo_url', 'expected_url'), [ pytest.param('https://upload.pypi.org/legacy/', 'https://pypi.org/project/', id='PyPI main'), pytest.param('https://test.pypi.org/legacy/', 'https://test.pypi.org/project/', id='PyPI test'), diff --git a/tests/project/test_config.py b/tests/project/test_config.py index 6692636d7..a395d80d2 100644 --- a/tests/project/test_config.py +++ b/tests/project/test_config.py @@ -22,8 +22,8 @@ def construct_matrix_data(env_name, config, overrides=None): # [{'version': ['9000']}, {'feature': ['bar']}] envs = {} - for matrix in matrices: - matrix = dict(matrix) + for matrix_data in matrices: + matrix = dict(matrix_data) variables = {} python_selected = False for variable in ('py', 'python'): @@ -1669,6 +1669,20 @@ def test_overrides_matrix_set_with_no_type_information(self, isolation): assert project_config.matrices['foo'] == construct_matrix_data('foo', env_config) def test_overrides_matrix_set_with_no_type_information_not_table(self, isolation): + project_config = ProjectConfig( + isolation, + { + 'envs': { + 'foo': { + 'matrix': [{'version': ['9000', '42']}, {'feature': ['bar']}], + 'overrides': {'matrix': {'version': {'bar': 9000}}}, + } + } + }, + PluginManager(), + ) + _ = project_config.envs + with pytest.raises( ValueError, match=( @@ -1676,19 +1690,6 @@ def test_overrides_matrix_set_with_no_type_information_not_table(self, isolation 'must be defined as a table with a `value` key' ), ): - project_config = ProjectConfig( - isolation, - { - 'envs': { - 'foo': { - 'matrix': [{'version': ['9000', '42']}, {'feature': ['bar']}], - 'overrides': {'matrix': {'version': {'bar': 9000}}}, - } - } - }, - PluginManager(), - ) - _ = project_config.envs project_config.finalize_env_overrides({}) @pytest.mark.parametrize('option', ARRAY_OPTIONS) diff --git a/tests/python/test_resolve.py b/tests/python/test_resolve.py index bfaa0ef7e..5b60fc030 100644 --- a/tests/python/test_resolve.py +++ b/tests/python/test_resolve.py @@ -37,7 +37,7 @@ def test_pypy(self): @pytest.mark.parametrize( - 'system, variant', + ('system', 'variant'), [ ('windows', 'shared'), ('windows', 'static'),