fix(x509): use backward compatible syntax for types#12927
Conversation
c9b98db to
05f3ded
Compare
|
@deivse @alex @reaperhulk I would appreciate a review / suggestions when you a minute. Thanks 🙏 |
|
I remember thinking if this is fine when making the original PR, yeah... I think we agreed during review that using the newer syntax shouldn't cause any issues, since it's an interface file, but it actually can, as I have encountered since. Normally mypy won't complain about this, but if you're running with min python version specified in mypy config (I think it can also pick it up from pyproject.toml), it will. I assume you have the min python version explicitly specified somewhere? Fortunately this should not be an issue outside of type checking - the .pyi file is purely for interface definitions and type checking information. I definitely agree this should be fixed though. |
alex
left a comment
There was a problem hiding this comment.
can you add a job to ci.yml, probably something like:
- {VERSION: "3.8", NOXSESSION: "flake"}
| NON_CRITICAL: Criticality | ||
|
|
||
| type MaybeExtensionValidatorCallback[T: x509.ExtensionType] = typing.Callable[ | ||
| T = typing.TypeVar("T", covariant=True, bound=x509.ExtensionType) |
There was a problem hiding this comment.
I think this should actually be contravariant, not covariant - this doesn't affect usage in the method definitions, but for the type aliases, since they are callables, we want them to be contravariant, I think. Please correct me if I'm wrong - my first encounter with covariance and friends.
From what I understood, making this covariant means that wherever a MaybeExtensionValidator[A] is accepted, a MaybeExtensionValidator[B] would also be accepted, where B is derived from A. But I don't think that's a good idea. Contravariance would mean that MaybeExtensionValidator[A] would be accepted wherever MaybeExtensionValidator[B] is accepted, and that seems potentially useful in some specific cases - i.e. for example the user might want to create some extension validation callback that accepts any type (type hint would be for x509.ExtensionType) and re-routes the validation to some other structure in their code.
There was a problem hiding this comment.
The mypy docs describe why contravariance makes sense for callables better than I do.
There was a problem hiding this comment.
right. so, do you feel we need to put explicit contravariant=True or leave it default?
There was a problem hiding this comment.
Explicitly mark contravariant I think, because with the old type syntax it's neither by default, and the new one defaulted this to contravariant. I think it's best to keep it that way, since the use case of passing in an extension validator that accepts any extension can be valid under some very specific circumstances (and I'm pretty sure I did that in tests).
@alex can you please double check that my understanding of co/contravariance is correct when you have a chance? 😄
There was a problem hiding this comment.
I think leaving it blank makes it invariant, and that's fine?
There was a problem hiding this comment.
Imo that's a bit needlessly prohibitive since then you wouldn't be able to pass in an extension validator that accepts any extension. I'm pretty sure that would make type checking fail for the tests. The real world use cases I can come up with are extremely contrived, but I think it's worth keeping it contravariant just for the tests since it doesn't hurt anything imo.
There was a problem hiding this comment.
Not sure about the tests tbh, basically either nothing or explicitly contravariant should be fine. Not a deal breaker imo.
There was a problem hiding this comment.
My understanding is that inavariant is the same behavior as the prior type annotation:
>>> def f[T: datetime.datetime](t: T): pass
...
>>> f.__annotations__
{'t': T}
>>> t = f.__annotations__["t"]
>>> t.__covariant__
False
>>> t.__contravariant__
False
There was a problem hiding this comment.
this is different since it's a function accepting a type, there any sort of variance is not defined since the function itself is not generic, it just accepts a generic argument. If you defined a type alias for a callable with the new syntax I'm quite sure it would be contravariant. (Or alternatively a function which accepts a generic callable.)
The idea is that when u accept a callable you want to accept a callable for a specific type or a callable for a more generic type - all you care about is that you can call it with your type.
There was a problem hiding this comment.
(at least mypy docs explicitly say that generic callables are contravariant by default with the new syntax)
|
@alex added, seems there are other issue on Python 3.8, probably unrelated to this one. |
|
Grumble. Ok I think what I'll do is send a separate PR to resolve those, so you don't have to debug all of our (apparently broken) type annotations. |
should unblock pyca#12927
05f3ded to
0e72897
Compare
|
Ok you should be able to merge/rebase main and get green. |
0e72897 to
23b0ee4
Compare
|
(And we need to bring back the 3.8 flake job) |
|
doh. missed one #12929 |
|
@alex still getting some issues on Py 3.8: |
|
I'll rebase when it is merged ... |
|
Ok, it's merged |
1d23154 to
ea374dc
Compare
ea374dc to
fd3860a
Compare
should unblock pyca#12927
* fix(x509): use backward compatible syntax for types * add Python 3.8 flake to ci
* mypy cleanups for Python 3.8 (#12928) should unblock #12927 * fix typing on release.py with older python (#12929) * fix(x509): use backward compatible syntax for types (#12927) * fix(x509): use backward compatible syntax for types * add Python 3.8 flake to ci * Backport mypy fixes for release * sigh * sigh --------- Co-authored-by: Ivan Shcheklein <shcheklein@gmail.com>
An attempt to fix the issue we are hitting on
mypyPython 3.9 (but also I think it won't work with Python 3.9 itself as well):It was introduced originally here: 4cfd7b1
I would appreciate a review since I'm definitely not a Python types expert.