add numcodec protocol#3318
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3318 +/- ##
==========================================
+ Coverage 94.51% 94.55% +0.04%
==========================================
Files 78 79 +1
Lines 9423 9448 +25
==========================================
+ Hits 8906 8934 +28
+ Misses 517 514 -3
🚀 New features to boost your workflow:
|
|
The way our code coverage works, class and function definitions are not counted as tested if they are imported by pytest prior to running actual tests. Pytest imports from a lot of our library due to fixtures defined in This means adding new functions always reduces coverage, because the function definition is uncovered. |
e5ffc33 to
ef31c5b
Compare
| overwrite=True, | ||
| zarr_format=zarr_format, | ||
| compressors=compressors, | ||
| compressors=compressors, # type: ignore[arg-type] |
There was a problem hiding this comment.
There's a lot of type: ignore comments currently dotted throughout - what's the reason for that? Is it perhaps because numcodecs.abc.Codec doesn't currently conform to the new protocol?
There was a problem hiding this comment.
this particular example is a test, and if you look a few lines above you will see that compressors is either None or the string "auto", and mypy models this as str | None, leading to this error:
tests/test_api.py:1285: error: Argument "compressors" to "create_array" has incompatible type "str | None"; expected "CompressorsLike" [arg-type]
I suspect the other type: ignore statements were added for different reasons
Spinning this question out into the main thread: without type annotations on |
|
To make sure I understand, does passing an existing numcodecs codec to |
Shouldn't it annotate our expectations, but allow for the (one?) exception to mark itself as non compliant? We probably don't want any other codecs making Object, and this is a way to say that. In fact, it raises the other question, for a different discussion: is having the pickle protocol reasonable? |
Yes, which is why in this PR I am annotating the
It might be reasonable for some applications (it was evidently reasonable enough to get implemented in the first place). It's also incredibly dangerous, because it performs arbitrary code execution. |
this is a great question, and the answer depends on which type checker you ask. if we take this script: # /// script
# requires-python = ">=3.11"
# dependencies = [
# "zarr"
# ]
# ///
import zarr
from numcodecs import GZip
import numcodecs
from zarr.abc.numcodec import Numcodec
a: Numcodec = GZip()
b: numcodecs.abc.Codec = GZip()mypy reports no problems: but the more thorough based-pyright type checker complains about both so, tldr is that the status quo is broken because numcodecs doesn't support type checking, AND the new protocol is using a too-narrow type. i'll look into fixing this, but it's important to keep in mind that the status quo is broken. edit: changing the numcodecs annotation from |
| from typing_extensions import Protocol | ||
|
|
||
|
|
||
| class Numcodec(Protocol): |
There was a problem hiding this comment.
Could this work with https://docs.python.org/3/library/typing.html#typing.runtime_checkable?
There was a problem hiding this comment.
I tried :( but I learned that @runtime_checkable doesn't work for protocols with non-methods (i.e., attributes), and the numcodecs.abc.Codec ABC uses codec_id as an attribute. I'm not 100% sure we need the codec_id here, but if we ever wanted to register these codecs, then it would be important.
There was a problem hiding this comment.
important context that I forgot when I answered this question: given the structure of Numcodec, runtime_checkable would work for isinstance checks, but not for issubclass checks, and I think there are places where we need the latter. But we should revisit this later if it turns out that we don't need issubclass, or if we want to use isinstance and rely on a custom function for issubclass.
This PR adds a protocol to model
numcodecs.abc.Codec. The motivation for this protocol is to ensure that we can process external codecs that adhere to the numcodecs API without needing numcodecs as a dependency.TODO:
docs/user-guide/*.rstchanges/