Skip to content
Draft
Show file tree
Hide file tree
Changes from 8 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
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ jobs:
pre-commit run --all-files typos
pre-commit run --all-files nbstripout
pre-commit run --all-files ruff-check
pre-commit run --all-files mypy
pre-commit run --all-files ty
64 changes: 21 additions & 43 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,47 +32,25 @@ repos:
- id: ruff-format
files: ^((skore|skore-hub-project|skore-local-project)/(hatch|src|tests))|(examples)/

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
- repo: local
hooks:

- id: mypy
pass_filenames: false
alias: mypy-skore
name: mypy skore/
files: ^skore/
args: [--config-file=skore/pyproject.toml, skore]
additional_dependencies:
# from dependencies
- IPython
- anywidget
- ipywidgets
- joblib
- matplotlib
- numpy
- pandas
- plotly
- rich
- scikit-learn
- skrub
- seaborn
# from test dependencies
- polars
- pyarrow
- scipy-stubs

- id: mypy
pass_filenames: false
alias: mypy-skore-hub-project
name: mypy skore-hub-project/
files: ^skore-hub-project/
args: [--config-file=skore-hub-project/pyproject.toml, skore-hub-project]
additional_dependencies: [skore, blake3, httpx, orjson, pandas-stubs, pydantic]

- id: mypy
pass_filenames: false
alias: mypy-skore-local-project
name: mypy skore-local-project/
files: ^skore-local-project/
args: [--config-file=skore-local-project/pyproject.toml, skore-local-project]
additional_dependencies: [skore]
- id: ty
alias: ty-skore
name: ty skore/
entry: uv run ty check --project skore
language: system
pass_filenames: false

- id: ty
alias: ty-skore-hub-project
name: ty skore-hub-project/
entry: uv run ty check --project skore-hub-project
language: system
pass_filenames: false

- id: ty
alias: ty-skore-local-project
name: ty skore-local-project/
entry: uv run ty check --project skore-local-project
language: system
pass_filenames: false
28 changes: 14 additions & 14 deletions skore-hub-project/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,18 @@ convention = "numpy"
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["D"]

[tool.mypy]
exclude = ["hatch/", "tests/"]
strict = true
Copy link
Collaborator

@thomass-dev thomass-dev Feb 19, 2026

Choose a reason for hiding this comment

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

This change has to be discussed, as ty doesn't have a strict mode for now and we would to be strict as much as possible in skore-hub-project and skore-local-project.

https://docs.astral.sh/ty/reference/typing-faq/#does-ty-have-a-strict-mode

Could you please list me the rules that will not be applied with this change?


[[tool.mypy.overrides]]
follow_untyped_imports = true
module = ["skore.*"]

[[tool.mypy.overrides]]
ignore_missing_imports = true
module = [
"joblib.*",
"scipy.*",
"sklearn.*",
[tool.ty.src]
exclude = ["hatch/**", "tests/**"]

[tool.ty.analysis]
allowed-unresolved-imports = [
"joblib.**",
"scipy.**",
"sklearn.**",
]

[[tool.ty.overrides]]
include = ["skore/**"]

[tool.ty.overrides.analysis]
respect-type-ignore-comments = true
21 changes: 12 additions & 9 deletions skore-hub-project/src/skore_hub_project/artifact/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from abc import ABC, abstractmethod
from contextlib import AbstractContextManager, nullcontext
from functools import cached_property
from typing import cast

from pydantic import BaseModel, ConfigDict, Field, computed_field

Expand Down Expand Up @@ -55,7 +56,7 @@ def content_to_upload(self) -> Generator[str, None, None]:
yield "<str>"
"""

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def checksum(self) -> str | None:
"""Checksum used to identify the content of the artifact."""
Expand All @@ -65,11 +66,13 @@ def checksum(self) -> str | None:
contextmanager = nullcontext(contextmanager)

with contextmanager as content:
if content is not None:
return upload(
project=self.project,
content=content,
content_type=self.content_type,
)

return None
if content is None:
return None

content = cast(str | bytes, content)

return upload(
project=self.project,
content=content,
content_type=self.content_type,
)
2 changes: 1 addition & 1 deletion skore-hub-project/src/skore_hub_project/metric/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Metric(BaseModel, ABC, Generic[Report]):
greater_is_better: bool | None = Field(init=False)
position: int | None = Field(init=False)

@computed_field # type: ignore[prop-decorator]
@computed_field
@property
def value(self) -> float | None:
"""The value of the metric."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ def model_post_init(self, _: Any) -> None: # noqa: D102
self.__sample_to_class_index = None
self.__classes = None

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def dataset_size(self) -> int:
"""Size of the dataset."""
return len(self.report.X)

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def splitting_strategy(self) -> dict[str, Any]:
"""
Expand Down Expand Up @@ -240,21 +240,21 @@ def splitting_strategy(self) -> dict[str, Any]:

groups: list[int] | None = None

@computed_field # type: ignore[prop-decorator]
@computed_field
@property
def class_names(self) -> list[str] | None:
"""In classification, the class names of the dataset used in the report."""
return self.__classes

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def target_range(self) -> list[float] | None:
"""The range of the target values of the dataset used in the report."""
if self.__classes:
return None
return [float(self.report.y.min()), float(self.report.y.max())]

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def estimators(self) -> list[EstimatorReportPayload]:
"""The estimators used in each split by the report in a payload format."""
Expand Down
16 changes: 8 additions & 8 deletions skore-hub-project/src/skore_hub_project/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,20 @@ class ReportPayload(BaseModel, ABC, Generic[Report]):

model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)

METRICS: ClassVar[tuple[type[Metric[Report]], ...]]
MEDIAS: ClassVar[tuple[type[Media[Report]], ...]]
METRICS: ClassVar[tuple[type[Metric], ...]]
MEDIAS: ClassVar[tuple[type[Media], ...]]

project: Project = Field(repr=False, exclude=True)
report: Report = Field(repr=False, exclude=True)
key: str

@computed_field # type: ignore[prop-decorator]
@computed_field
@property
def estimator_class_name(self) -> str:
"""The name of the report's estimator."""
return self.report.estimator_name_

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def dataset_fingerprint(self) -> str:
"""The hash of the targets in the test-set."""
Expand All @@ -81,13 +81,13 @@ def dataset_fingerprint(self) -> str:
),
)

@computed_field # type: ignore[prop-decorator]
@computed_field
@property
def ml_task(self) -> str:
"""The type of ML task covered by the report."""
return self.report.ml_task

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def metrics(self) -> list[Metric[Report]]:
"""
Expand Down Expand Up @@ -128,7 +128,7 @@ def metrics(self) -> list[Metric[Report]]:

return [metric for metric in metrics if metric.value is not None]

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def medias(self) -> list[Media[Report]]:
"""
Expand All @@ -151,7 +151,7 @@ def medias(self) -> list[Media[Report]]:

return payloads

@computed_field # type: ignore[prop-decorator]
@computed_field
@cached_property
def pickle(self) -> Pickle:
"""
Expand Down
21 changes: 9 additions & 12 deletions skore-local-project/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,14 @@ convention = "numpy"
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["D"]

[tool.mypy]
exclude = ["hatch/", "tests/"]
strict = true

[[tool.mypy.overrides]]
follow_untyped_imports = true
module = ["skore.*"]
[tool.ty.src]
exclude = [
"hatch/**",
"tests/**",
]

[[tool.mypy.overrides]]
ignore_missing_imports = true
module = [
"diskcache.*",
"joblib.*",
[tool.ty.analysis]
allowed-unresolved-imports = [
"diskcache.**",
"joblib.**",
]
16 changes: 8 additions & 8 deletions skore-local-project/src/skore_local_project/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from diskcache import Cache

Cache = partial(Cache, size_limit=float("inf"), cull_limit=0, eviction=None)
StorageCache = partial(Cache, size_limit=float("inf"), cull_limit=0, eviction=None)


class DirectoryDoesNotExist(Exception):
Expand All @@ -28,7 +28,7 @@ class DiskCacheStorage:

Attributes
----------
storage : Cache
storage : StorageCache
The underlying diskcache Cache object.
"""

Expand Down Expand Up @@ -103,7 +103,7 @@ def __getitem__(self, key: str) -> Any:
KeyError
If the key is not found in the storage.
"""
with Cache(self.directory) as storage:
with StorageCache(self.directory) as storage:
return storage[key]

def __setitem__(self, key: str, value: Any) -> None:
Expand All @@ -117,7 +117,7 @@ def __setitem__(self, key: str, value: Any) -> None:
value : Any
The value to store.
"""
with Cache(self.directory) as storage:
with StorageCache(self.directory) as storage:
storage[key] = value

def __delitem__(self, key: str) -> None:
Expand All @@ -134,7 +134,7 @@ def __delitem__(self, key: str) -> None:
KeyError
If the key is not found in the storage.
"""
with Cache(self.directory) as storage:
with StorageCache(self.directory) as storage:
del storage[key]

def keys(self) -> Iterator[str]:
Expand All @@ -146,7 +146,7 @@ def keys(self) -> Iterator[str]:
Iterator[str]
An iterator yielding all keys in the storage.
"""
with Cache(self.directory) as storage:
with StorageCache(self.directory) as storage:
yield from storage

def values(self) -> Iterator[Any]:
Expand All @@ -158,7 +158,7 @@ def values(self) -> Iterator[Any]:
Iterator[Any]
An iterator yielding all values in the storage.
"""
with Cache(self.directory) as storage:
with StorageCache(self.directory) as storage:
for key in storage:
yield storage[key]

Expand All @@ -171,7 +171,7 @@ def items(self) -> Iterator[tuple[str, Any]]:
Iterator[tuple[str, Any]]
An iterator yielding all (key, value) pairs in the storage.
"""
with Cache(self.directory) as storage:
with StorageCache(self.directory) as storage:
for key in storage:
yield (key, storage[key])

Expand Down
17 changes: 2 additions & 15 deletions skore/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,5 @@ convention = "numpy"
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["D"]

[tool.mypy]
exclude = ["src/skore/_externals/", "hatch/", "tests/"]

[[tool.mypy.overrides]]
ignore_missing_imports = true
module = [
"ipywidgets.*",
"jinja2.*",
"joblib.*",
"pandas.*",
"plotly.*",
"seaborn.*",
"sklearn.*",
"skrub.*",
]
[tool.ty.src]
exclude = ["hatch/**", "src/skore/_externals/**", "tests/**"]
Loading