Skip to content

More consistency checks for dependencies #4990

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 1, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion tests/check_consistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,28 @@ def check_versions():
assert not extra, f"Versions not in modules: {extra}"


def _strip_dep_version(dependency):
dep_version_pos = len(dependency)
for pos, c in enumerate(dependency):
if c in "=<>":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there is a semicolon? Example from mypy test-requirements.txt:

flake8-bugbear; python_version >= '3.5'

We check for spaces, but somebody might write something like this:

types-foo;python_version>='3.5'

Maybe use a regexp to validate the version string so that we don't check for bad things but ensure that only expected things exist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, there should not be semicolons, requires is already a list.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I didn't notice what is in the second part, I think we may not support this initially.

dep_version_pos = pos
break
stripped = dependency[:dep_version_pos]
rest = dependency[dep_version_pos:]
if not rest:
return stripped, "", ""
number_pos = 0
for pos, c in enumerate(rest):
if c not in "=<>":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above.

number_pos = pos
break
relation = rest[:number_pos]
version = rest[number_pos:]
return stripped, relation, version


def check_metadata():
known_distributions = set(os.listdir("stubs"))
for distribution in os.listdir("stubs"):
with open(os.path.join("stubs", distribution, "METADATA.toml")) as f:
data = toml.loads(f.read())
Expand All @@ -146,9 +167,20 @@ def check_metadata():
assert isinstance(data.get("python3", True), bool), f"Invalid python3 value for {distribution}"
assert isinstance(data.get("requires", []), list), f"Invalid requires value for {distribution}"
for dep in data.get("requires", []):
# TODO: add more validation here.
assert isinstance(dep, str), f"Invalid dependency {dep} for {distribution}"
assert dep.startswith("types-"), f"Only stub dependencies supported, got {dep}"
dep = dep[len("types-"):]
for space in " \t\n":
assert space not in dep, f"For consistency dependency should not have whitespace: {dep}"
assert ";" not in dep, f"Semicolons in dependencies are not supported, got {dep}"
stripped, relation, dep_version = _strip_dep_version(dep)
assert stripped in known_distributions, f"Only dependencies from typeshed are supported, got {stripped}"
if relation:
msg = f"Bad version in dependency {dep}"
assert relation in {"==", ">", ">=", "<", "<="}, msg
assert version.count(".") <= 2, msg
for part in version.split("."):
assert part.isnumeric(), msg


if __name__ == "__main__":
Expand Down