Skip to content

Commit

Permalink
Raise an error if multiple extras with the same (normalized) name are…
Browse files Browse the repository at this point in the history
… found, or if invalid names are found.
  • Loading branch information
domdfcoding committed May 3, 2022
1 parent 14eeabb commit 91d3c63
Show file tree
Hide file tree
Showing 11 changed files with 23 additions and 81 deletions.
20 changes: 5 additions & 15 deletions pyproject_parser/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,6 @@ def parse_optional_dependencies(
"""

parsed_optional_dependencies: Dict[str, Set[ComparableRequirement]] = dict()
normalized_names: Set[str] = set() # remove for part 2

optional_dependencies: Mapping[str, Any] = config["optional-dependencies"]

Expand All @@ -961,32 +960,23 @@ def parse_optional_dependencies(

path = ("project", "optional-dependencies", extra)

if normalized_extra in normalized_names: # parsed_optional_dependencies for part 2
warnings.warn(
if normalized_extra in parsed_optional_dependencies:
raise BadConfigError(
f"{construct_path(path)!r}: "
f"Multiple extras were defined with the same normalized name of {normalized_extra!r}",
PyProjectDeprecationWarning,
)
# For part 2
# raise BadConfigError(
# f"{construct_path(path)!r}: "
# f"Multiple extras were defined with the same normalized name of {normalized_extra!r}",
# )

# https://packaging.python.org/specifications/core-metadata/#provides-extra-multiple-use
# if not extra_re.match(normalized_extra):
if not (extra.isidentifier() or extra_re.match(normalized_extra)):
if not extra_re.match(normalized_extra):
raise TypeError(f"Invalid extra name {extra!r} ({extra_re.match(normalized_extra)})")

self.assert_sequence_not_str(dependencies, path=path)

parsed_optional_dependencies[extra] = set() # normalized_extra for part 2
normalized_names.add(normalized_extra) # Remove for part 2
parsed_optional_dependencies[normalized_extra] = set()

for idx, dep in enumerate(dependencies):
if isinstance(dep, str):
# normalized_extra for part 2
parsed_optional_dependencies[extra].add(ComparableRequirement(dep))
parsed_optional_dependencies[normalized_extra].add(ComparableRequirement(dep))
else:
raise TypeError(
f"Invalid type for 'project.optional-dependencies.{extra}[{idx}]': "
Expand Down
3 changes: 0 additions & 3 deletions repo_helper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,3 @@ intersphinx_mapping:

exclude_files:
- contributing

tox_unmanaged:
- coverage:report
43 changes: 1 addition & 42 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# stdlib
import json
import re
import subprocess
import warnings
from typing import Optional

# 3rd party
Expand Down Expand Up @@ -109,53 +107,14 @@ def test_check_extra_deprecation(
(tmp_pathplus / "pyproject.toml").write_clean(toml_string)
cli_runner.mix_stderr = False

with in_directory(tmp_pathplus), warnings.catch_warnings():
warnings.simplefilter("error")
with in_directory(tmp_pathplus):
result: Result = cli_runner.invoke(check, catch_exceptions=False)

assert result.exit_code == 1
assert result.stdout == "Validating 'pyproject.toml'\n"
advanced_file_regression.check(result.stderr)


@pytest.mark.parametrize(
"toml_string",
[
pytest.param(
'[project]\nname = "foo"\nversion = "1.2.3"\n[project.optional-dependencies]\n"dev_test" = []\n"dev-test" = []',
id="duplicate_extra_1",
),
pytest.param(
'[project]\nname = "foo"\nversion = "1.2.3"\n[project.optional-dependencies]\n"dev-test" = []\n"dev_test" = []',
id="duplicate_extra_2",
),
pytest.param(
'[project]\nname = "foo"\nversion = "1.2.3"\n[project.optional-dependencies]\n"dev.test" = []\n"dev_test" = []',
id="duplicate_extra_3",
),
]
)
def test_check_extra_deprecation_warning(
toml_string: str,
tmp_pathplus: PathPlus,
cli_runner: CliRunner,
advanced_file_regression: AdvancedFileRegressionFixture,
):
(tmp_pathplus / "pyproject.toml").write_clean(toml_string)

args = ["pyproject-parser", "check"]

with in_directory(tmp_pathplus):
process = subprocess.run(
args,
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
)
assert process.returncode == 0

advanced_file_regression.check(process.stdout.decode("UTF-8"))


@pytest.mark.parametrize(
"toml_string, match",
[
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
An error occurred: 'project.optional-dependencies.dev-test': Multiple extras were defined with the same normalized name of 'dev-test'
BadConfigError: 'project.optional-dependencies.dev-test': Multiple extras were defined with the same normalized name of 'dev-test'
Use '--traceback' to view the full traceback.
Aborted!
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
An error occurred: 'project.optional-dependencies.dev_test': Multiple extras were defined with the same normalized name of 'dev-test'
BadConfigError: 'project.optional-dependencies.dev_test': Multiple extras were defined with the same normalized name of 'dev-test'
Use '--traceback' to view the full traceback.
Aborted!
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
An error occurred: 'project.optional-dependencies.dev_test': Multiple extras were defined with the same normalized name of 'dev-test'
BadConfigError: 'project.optional-dependencies.dev_test': Multiple extras were defined with the same normalized name of 'dev-test'
Use '--traceback' to view the full traceback.
Aborted!

This file was deleted.

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def test_extra_deprecation(

(tmp_pathplus / "pyproject.toml").write_clean(config)

with in_directory(tmp_pathplus), pytest.warns(PyProjectDeprecationWarning, match=match):
with in_directory(tmp_pathplus), pytest.raises(BadConfigError, match=match):
PEP621Parser().parse(dom_toml.load(tmp_pathplus / "pyproject.toml")["project"])


Expand Down
21 changes: 10 additions & 11 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# * testenv:coverage
# * flake8
# * coverage:run
# * coverage:report
# * check-wheel-contents
# * pytest

Expand Down Expand Up @@ -169,15 +170,6 @@ unused-arguments-ignore-variadic-names = True
[coverage:run]
plugins = coverage_pyver_pragma
[check-wheel-contents]
ignore = W002
toplevel = pyproject_parser
package = pyproject_parser
[pytest]
addopts = --color yes --durations 25
timeout = 300
[coverage:report]
fail_under = 97.5
exclude_lines =
Expand All @@ -188,5 +180,12 @@ exclude_lines =
if TYPE_CHECKING:
if typing.TYPE_CHECKING:
if __name__ == .__main__.:
omit =
.tox/**/*.py
[check-wheel-contents]
ignore = W002
toplevel = pyproject_parser
package = pyproject_parser
[pytest]
addopts = --color yes --durations 25
timeout = 300

0 comments on commit 91d3c63

Please sign in to comment.