Skip to content
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

fix(core): Typing in generic + network #700

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ coverage: ## Target to combine and report coverage.
lint: ## Lint all files in the project, which we also run in pre-commit
poetry run pre-commit run -a

mypy-core-report:
poetry run mypy --config-file pyproject.toml core | poetry run python scripts/mypy_report.py

docs: ## Build the docs for the project
poetry run sphinx-build -nW . docs/_build

Expand Down
4 changes: 2 additions & 2 deletions core/testcontainers/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from typing import Optional
from typing import Any, Optional

Check warning on line 13 in core/testcontainers/core/generic.py

View check run for this annotation

Codecov / codecov/patch

core/testcontainers/core/generic.py#L13

Added line #L13 was not covered by tests
from urllib.parse import quote

from testcontainers.core.container import DockerContainer
Expand Down Expand Up @@ -55,7 +55,7 @@
host: Optional[str] = None,
port: Optional[int] = None,
dbname: Optional[str] = None,
**kwargs,
**kwargs: Any,
) -> str:
if raise_for_deprecated_parameter(kwargs, "db_name", "dbname"):
raise ValueError(f"Unexpected arguments: {','.join(kwargs)}")
Expand Down
10 changes: 6 additions & 4 deletions core/testcontainers/core/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from typing import Optional
from typing import Any, Optional

from testcontainers.core.docker_client import DockerClient

Expand All @@ -21,12 +21,14 @@ class Network:
Network context manager for programmatically connecting containers.
"""

def __init__(self, docker_client_kw: Optional[dict] = None, docker_network_kw: Optional[dict] = None) -> None:
def __init__(
self, docker_client_kw: Optional[dict[str, Any]] = None, docker_network_kw: Optional[dict[str, Any]] = None
):
self.name = str(uuid.uuid4())
self._docker = DockerClient(**(docker_client_kw or {}))
self._docker_network_kw = docker_network_kw or {}

def connect(self, container_id: str, network_aliases: Optional[list] = None):
def connect(self, container_id: str, network_aliases: Optional[list[str]] = None) -> None:
self._network.connect(container_id, aliases=network_aliases)

def remove(self) -> None:
Expand All @@ -40,5 +42,5 @@ def create(self) -> "Network":
def __enter__(self) -> "Network":
return self.create()

def __exit__(self, exc_type, exc_val, exc_tb) -> None:
def __exit__(self, exc_type, exc_val, exc_tb) -> None: # type: ignore[no-untyped-def]
self.remove()
4 changes: 2 additions & 2 deletions core/tests/test_docker_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ def test_docker_client_login():
mock_parse_docker_auth_config = MagicMock(spec=parse_docker_auth_config)
mock_utils = MagicMock()
mock_utils.parse_docker_auth_config = mock_parse_docker_auth_config
TestAuth = namedtuple("Auth", "value")
mock_parse_docker_auth_config.return_value = [TestAuth("test")]
Auth = namedtuple("Auth", "value")
mock_parse_docker_auth_config.return_value = [Auth("test")]

with (
mock.patch.object(c, "_docker_auth_config", "test"),
Expand Down
2 changes: 1 addition & 1 deletion core/tests/test_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from testcontainers.core.config import RYUK_IMAGE


def assert_in_with_value(labels: dict, label: str, value: str, known_before_test_time: bool) -> None:
def assert_in_with_value(labels: dict[str, str], label: str, value: str, known_before_test_time: bool):
assert label in labels
if known_before_test_time:
assert labels[label] == value
Expand Down
2 changes: 1 addition & 1 deletion core/tests/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,6 @@ def test_network_has_labels():
try:
network.create()
network = network._docker.client.networks.get(network_id=network.id)
assert LABEL_SESSION_ID in network.attrs.get("Labels")
assert LABEL_SESSION_ID in network.attrs.get("Labels") # type: ignore[attr-defined]
finally:
network.remove()
60 changes: 30 additions & 30 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ chroma = ["chromadb-client"]
trino = ["trino"]

[tool.poetry.group.dev.dependencies]
mypy = "1.7.1"
mypy = "1.11.2"
pre-commit = "^3.6"
pytest = "7.4.3"
pytest-cov = "4.1.0"
Expand Down Expand Up @@ -283,8 +283,9 @@ namespace_packages = true
explicit_package_bases = true
pretty = true
show_error_codes = true
warn_return_any = true
strict = true
fast_module_lookup = true
# fast_module_lookup = true
modules = ["testcontainers.core"]
mypy_path = [
"core",
Expand Down
35 changes: 35 additions & 0 deletions scripts/mypy_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Description: This script reads the output of mypy and generates a summary of errors by file.

import re
import sys

from rich.console import Console
from rich.table import Table

# Regular expression to match file path and error count
pattern = r"(.*\.py:\d+):\s+error: (.*)"

error_dict = {}

for line in sys.stdin:
match = re.search(pattern, line)
if match:
# Extract file path and error message
file_path, _ = match.group(1).split(":")
error_message = match.group(2)

if file_path not in error_dict:
error_dict[file_path] = 1
else:
error_dict[file_path] += 1

table = Table(title="Error Summary")
table.add_column("File Path")
table.add_column("Errors", justify="left")

for file_path, error_count in error_dict.items():
table.add_row(file_path, str(error_count))

console = Console()
console.print(table)
console.print(f"[red]Found {sum(error_dict.values())} errors in {len(error_dict)} files.[/red]")