-
Notifications
You must be signed in to change notification settings - Fork 260
Force type hints #233
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
Force type hints #233
Changes from all commits
2461a7b
15c2bc3
cc70d69
75d6ef6
38bbcff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,20 @@ | ||
| [flake8] | ||
| max-line-length = 88 | ||
| ignore = E501, E203, W503 | ||
| per-file-ignores = __init__.py:F401 | ||
| ignore = E501, E203, W503, ANN101, ANN102 | ||
| mypy-init-return = True | ||
|
neersighted marked this conversation as resolved.
|
||
| per-file-ignores = | ||
| __init__.py:F401 | ||
| tests/test_*:ANN201 | ||
| tests/**/test_*:ANN201 | ||
| exclude = | ||
| .git | ||
| __pycache__ | ||
| setup.py | ||
| build | ||
| dist | ||
| releases | ||
| .venv | ||
| .tox | ||
| .mypy_cache | ||
| .pytest_cache | ||
| .vscode | ||
| .github | ||
| poetry_core/_vendor/ | ||
| poetry_core/utils/_compat.py | ||
| poetry_core/utils/_typing.py | ||
| tests/fixtures/ | ||
| tests/masonry/fixtures/ | ||
| poetry/core/_vendor/* | ||
| tests/fixtures/* | ||
| tests/**/fixtures/* | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -61,7 +61,9 @@ def _get_local(cls, match: Optional[Match[AnyStr]]) -> Optional[LocalSegmentType | |||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| @classmethod | ||||||||||||||
| def parse(cls, value: str, version_class: Optional[Type["PEP440Version"]] = None): | ||||||||||||||
| def parse( | ||||||||||||||
| cls, value: str, version_class: Optional[Type["PEP440Version"]] = None | ||||||||||||||
| ) -> "PEP440Version": | ||||||||||||||
|
Comment on lines
+64
to
+66
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you remove the
Suggested change
|
||||||||||||||
| match = cls._regex.search(value) if value else None | ||||||||||||||
| if not match: | ||||||||||||||
| raise InvalidVersion(f"Invalid PEP 440 version: '{value}'") | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import dataclasses | ||
| import math | ||
|
|
||
| from typing import Any | ||
| from typing import Optional | ||
| from typing import Tuple | ||
| from typing import Union | ||
|
|
@@ -32,7 +33,7 @@ class PEP440Version: | |
| int, Release, ReleaseTag, ReleaseTag, ReleaseTag, Tuple[Union[int, str], ...] | ||
| ] = dataclasses.field(default=None, init=False, compare=True) | ||
|
|
||
| def __post_init__(self): | ||
| def __post_init__(self) -> None: | ||
| if self.local is not None and not isinstance(self.local, tuple): | ||
| object.__setattr__(self, "local", (self.local,)) | ||
|
|
||
|
|
@@ -46,7 +47,11 @@ def __post_init__(self): | |
|
|
||
| object.__setattr__(self, "_compare_key", self._make_compare_key()) | ||
|
|
||
| def _make_compare_key(self): | ||
| def _make_compare_key( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, this is a complicated type. Is there any way to clean this up with NewType, a refactor with an object, or similar?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was happy, that PyCharm was doing this for me 😆 IMO refactoring should be done in another PR, because the purpose of this PR is to enforce type hints in the future.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a brutal type signature :)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried to understand the code and IMO the signature can be written more easily. See code change. |
||
| self, | ||
| ) -> Tuple[ | ||
| int, Release, ReleaseTag, ReleaseTag, ReleaseTag, Tuple[Tuple[float, str], ...] | ||
| ]: | ||
| """ | ||
| This code is based on the implementation of packaging.version._cmpkey(..) | ||
| """ | ||
|
|
@@ -103,7 +108,7 @@ def patch(self) -> Optional[int]: | |
| def non_semver_parts(self) -> Optional[Tuple[int]]: | ||
| return self.release.extra | ||
|
|
||
| def to_string(self, short=False): | ||
| def to_string(self, short: bool = False) -> str: | ||
| dash = "-" if not short else "" | ||
|
|
||
| version_string = dash.join( | ||
|
|
@@ -209,7 +214,7 @@ def first_prerelease(self) -> "PEP440Version": | |
| epoch=self.epoch, release=self.release, pre=ReleaseTag(RELEASE_PHASE_ALPHA) | ||
| ) | ||
|
|
||
| def replace(self, **kwargs): | ||
| def replace(self, **kwargs: Any) -> "PEP440Version": | ||
| return self.__class__( | ||
| **{ | ||
| **{ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import sys | ||
|
|
||
| from pathlib import Path | ||
| from typing import TYPE_CHECKING | ||
| from typing import Callable | ||
|
|
||
| import pytest | ||
|
|
@@ -10,7 +11,12 @@ | |
| from tests.testutils import tempfile | ||
|
|
||
|
|
||
| def pytest_addoption(parser): | ||
| if TYPE_CHECKING: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you shouldn't need the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a convention I'm used to. If you need a module just for type hints, import it only in the It's easier to teach to other people ("Why are you sometime put import in that block and sometimes not?") and the overall chance that you have a circular import if you need this import just for type hint is quite big. TL;DR: I prefer to leave it as it is.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fair enough. there's some interesting background on it here - larryhastings/co_annotations#1 in general, it seems that
the Benevolent Dictator for Life seems to regard it is a painfully necessary hack. that said, it's also clear from the thread that it's far from settled. And using it everywhere instead of the small number of cases where you need it (do you definitely need it anywhere in this codebase?) is at least consistent. |
||
| from _pytest.config import Config | ||
| from _pytest.config.argparsing import Parser | ||
|
|
||
|
|
||
| def pytest_addoption(parser: "Parser") -> None: | ||
| parser.addoption( | ||
| "--integration", | ||
| action="store_true", | ||
|
|
@@ -20,15 +26,15 @@ def pytest_addoption(parser): | |
| ) | ||
|
|
||
|
|
||
| def pytest_configure(config): | ||
| def pytest_configure(config: "Config") -> None: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can use |
||
| config.addinivalue_line("markers", "integration: mark integration tests") | ||
|
|
||
| if not config.option.integration: | ||
| config.option.markexpr = "not integration" | ||
|
|
||
|
|
||
| def get_project_from_dir(base_directory): # type: (Path) -> Callable[[str], Path] | ||
| def get(name): # type: (str) -> Path | ||
| def get_project_from_dir(base_directory: Path) -> Callable[[str], Path]: | ||
| def get(name: str) -> Path: | ||
| path = base_directory / name | ||
| if not path.exists(): | ||
| raise FileNotFoundError(str(path)) | ||
|
|
@@ -38,45 +44,45 @@ def get(name): # type: (str) -> Path | |
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def project_source_root(): # type: () -> Path | ||
| def project_source_root() -> Path: | ||
| return Path(__file__).parent.parent | ||
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def project_source_test_root(): # type: () -> Path | ||
| def project_source_test_root() -> Path: | ||
| return Path(__file__).parent | ||
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def common_fixtures_directory(project_source_test_root): # type: (Path) -> Path | ||
| def common_fixtures_directory(project_source_test_root: Path) -> Path: | ||
| return project_source_test_root / "fixtures" | ||
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def common_project(common_fixtures_directory): # type: (Path) -> Callable[[str], Path] | ||
| def common_project(common_fixtures_directory: Path) -> Callable[[str], Path]: | ||
| return get_project_from_dir(common_fixtures_directory) | ||
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def masonry_fixtures_directory(project_source_test_root): # type: (Path) -> Path | ||
| def masonry_fixtures_directory(project_source_test_root: Path) -> Path: | ||
| return project_source_test_root / "masonry" / "builders" / "fixtures" | ||
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def masonry_project( | ||
| masonry_fixtures_directory, | ||
| ): # type: (Path) -> Callable[[str], Path] | ||
| masonry_fixtures_directory: Path, | ||
| ) -> Callable[[str], Path]: | ||
| return get_project_from_dir(masonry_fixtures_directory) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def temporary_directory(): # type: () -> Path | ||
| def temporary_directory() -> Path: | ||
| with tempfile.TemporaryDirectory(prefix="poetry-core") as tmp: | ||
| yield Path(tmp) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def venv(temporary_directory): # type: (Path) -> Path | ||
| def venv(temporary_directory: Path) -> Path: | ||
| venv_dir = temporary_directory / ".venv" | ||
| virtualenv.cli_run( | ||
| [ | ||
|
|
@@ -91,10 +97,10 @@ def venv(temporary_directory): # type: (Path) -> Path | |
|
|
||
|
|
||
| @pytest.fixture | ||
| def python(venv): # type: (Path) -> str | ||
| def python(venv: Path) -> str: | ||
| return (venv / "bin" / "python").as_posix() | ||
|
|
||
|
|
||
| @pytest.fixture() | ||
| def f(): # type: () -> Factory | ||
| def f() -> Factory: | ||
| return Factory() | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole file is very cargo-culted. Can we clean it up while we're in here?