Skip to content

Protocol and function signatures (projection and extraction) are technically incompatible, newer versions of ty doesn't like this #150

Open

Description

@brews

Newer versions of ty are flagging a problem with how we're "implementing" protocols with a dataclass.

The signature of the protocols and the signatures of the methods are not 100% compatible. We've kinda fudged our way around this and it looks like this is catching up.

Examples of the error from PR #145:

error[invalid-attribute-override]: Invalid override of attribute `pre_extract`
  --> src/isku/extract.py:60:5
   |
60 |     pre_extract: Callable[[xr.Dataset], xr.Dataset]
   |     ^^^^^^^^^^^ Type `(Dataset, /) -> Dataset` is not assignable to inherited type `(ds: Dataset) -> Dataset`
   |
  ::: src/isku/extract.py:27:9
   |
27 |     def pre_extract(self, ds: xr.Dataset) -> xr.Dataset:
   |         ----------- `ExtractionTemplate.pre_extract` declared here

error[invalid-attribute-override]: Invalid override of attribute `post_extract`
  --> src/isku/extract.py:61:5
   |
61 |     post_extract: Callable[[xr.Dataset], xr.Dataset]
   |     ^^^^^^^^^^^^ Type `(Dataset, /) -> Dataset` is not assignable to inherited type `(ds: Dataset) -> Dataset`
   |
  ::: src/isku/extract.py:33:9
   |
33 |     def post_extract(self, ds: xr.Dataset) -> xr.Dataset:
   |         ------------ `ExtractionTemplate.post_extract` declared here

error[call-non-callable]: Cannot instantiate abstract class `_SimpleExtractionTemplate`
  --> src/isku/extract.py:85:12
   |
85 |     return _SimpleExtractionTemplate(pre_extract=pre, post_extract=post)
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Abstract methods `pre_extract` and `post_extract` are unimplemented
   |
  ::: src/isku/extract.py:27:5
   |
27 |     def pre_extract(self, ds: xr.Dataset) -> xr.Dataset:
   |     --------------------------------------------------- `pre_extract` declared as abstract on superclass `ExtractionTemplate`
info: `ExtractionTemplate.pre_extract` is implicitly abstract because `ExtractionTemplate` is a `Protocol` class and `pre_extract` lacks an implementation
  --> src/isku/extract.py:16:7
   |
16 | class ExtractionTemplate(Protocol):
   |       ---------------------------- `ExtractionTemplate` declared here
info: The instance-attribute annotation for `pre_extract` does not override the abstract method
help: Either assign a value or add `ClassVar` to this declaration
  --> src/isku/extract.py:60:5
   |
60 |     pre_extract: Callable[[xr.Dataset], xr.Dataset]
   |     ----------- Instance-attribute declaration

error[invalid-attribute-override]: Invalid override of attribute `pre_project`
  --> src/isku/project.py:45:5
   |
45 |     pre_project: Callable[[xr.Dataset], xr.Dataset]
   |     ^^^^^^^^^^^ Type `(Dataset, /) -> Dataset` is not assignable to inherited type `(ds: Dataset) -> Dataset`
   |
  ::: src/isku/project.py:23:9
   |
23 |     def pre_project(self, ds: xr.Dataset) -> xr.Dataset:
   |         ----------- `ProjectionTemplate.pre_project` declared here

error[invalid-attribute-override]: Invalid override of attribute `project`
  --> src/isku/project.py:46:5
   |
46 |     project: Callable[[xr.Dataset], xr.Dataset]
   |     ^^^^^^^ Type `(Dataset, /) -> Dataset` is not assignable to inherited type `(ds: Dataset) -> Dataset`
   |
  ::: src/isku/project.py:29:9
   |
29 |     def project(self, ds: xr.Dataset) -> xr.Dataset:
   |         ------- `ProjectionTemplate.project` declared here

error[invalid-attribute-override]: Invalid override of attribute `post_project`
  --> src/isku/project.py:47:5
   |
47 |     post_project: Callable[[xr.Dataset], xr.Dataset]
   |     ^^^^^^^^^^^^ Type `(Dataset, /) -> Dataset` is not assignable to inherited type `(ds: Dataset) -> Dataset`
   |
  ::: src/isku/project.py:35:9
   |
35 |     def post_project(self, ds: xr.Dataset) -> xr.Dataset:
   |         ------------ `ProjectionTemplate.post_project` declared here

error[call-non-callable]: Cannot instantiate abstract class `_SimpleProjectionTemplate`
  --> src/isku/project.py:66:12
   |
66 |       return _SimpleProjectionTemplate(
   |  ____________^
67 | |         pre_project=pre,
68 | |         project=project,
69 | |         post_project=post,
70 | |     )
   | |_____^ Abstract methods `pre_project`, `project` and `post_project` are unimplemented
   |
  ::: src/isku/project.py:23:5
   |
23 |       def pre_project(self, ds: xr.Dataset) -> xr.Dataset:
   |       --------------------------------------------------- `pre_project` declared as abstract on superclass `ProjectionTemplate`
info: `ProjectionTemplate.pre_project` is implicitly abstract because `ProjectionTemplate` is a `Protocol` class and `pre_project` lacks an implementation
  --> src/isku/project.py:14:7
   |
14 | class ProjectionTemplate(Protocol):
   |       ---------------------------- `ProjectionTemplate` declared here
info: The instance-attribute annotation for `pre_project` does not override the abstract method
help: Either assign a value or add `ClassVar` to this declaration
  --> src/isku/project.py:45:5
   |
45 |     pre_project: Callable[[xr.Dataset], xr.Dataset]
   |     ----------- Instance-attribute declaration

Found 7 diagnostics

Need to find a solution to keep type checking happy without practically significant breaks. Meta class or constructor or wrapping something something...?

Activity

  1. changed the title [-]Protocol and function signatures (projection and extraction) are technically incompatible in newer versions of ty[/-] [+]Protocol and function signatures (projection and extraction) are technically incompatible, newer versions of ty doesn't like this[/+] on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions