Repository navigation
Conversation
|
These are all subclasses of |
|
@JelleZijlstra sure thing: Save this as import os
import yaml
def load_config(config_path: str) -> dict:
# define custom tag handler
def _join(loader: yaml.Loader, node: yaml.SequenceNode) -> str:
seq = loader.construct_sequence(node)
return os.path.join(*[str(i) for i in seq])
# register the tag handler
yaml.add_constructor("!join", _join)
# load config
with open(config_path, "r") as ymlfile:
config = yaml.load(ymlfile, Loader=yaml.Loader)
return configThen check with ❯ mypy example.py
example.py:13: error: Argument 2 to "add_constructor" has incompatible type "Callable[[Loader, SequenceNode], str]"; expected "Callable[[Union[Loader, FullLoader, UnsafeLoader], Node], Any]" [arg-type]
Found 1 error in 1 file (checked 1 source file) |
This comment has been minimized.
This comment has been minimized.
|
Thanks for the code sample! Our stub for @overload
def add_constructor(
tag: str, constructor: Callable[[Loader | FullLoader | UnsafeLoader, Node], Any], Loader: None = ...
) -> None: ...
@overload
def add_constructor(tag: str, constructor: Callable[[_Constructor, Node], Any], Loader: type[_Constructor]) -> None: ...
Maybe the |
|
@JelleZijlstra I see what you mean. So basically, it won't work because what is defined in the |
|
@JelleZijlstra Those loaders make use of This would suggest that the allowed node types for @overload
def add_constructor(
tag: str, constructor: Callable[[Loader | FullLoader | UnsafeLoader, MappingNode | ScalarNode | SequenceNode], Any], Loader: None = ...
) -> None: ...
@overload
def add_constructor(tag: str, constructor: Callable[[_Constructor, MappingNode | ScalarNode | SequenceNode], Any], Loader: type[_Constructor]) -> None: ...What do you think? |
|
These proposed types imply that the constructor callable must accept all of |
0ebfc92 to
fccb483
Compare
This comment has been minimized.
This comment has been minimized.
|
I haven't looked into how to fix your problem, but I concur with @JelleZijlstra that this PR won't fix anything, unfortunately. The proposed union would be redundant, since If the problem is still present, please open an issue, and we can try to figure out how to fix it. |
|
@AlexWaygood I've been intending to look into this issue further and potentially finding the right fix, however, life and work have gotten in the way. I'll probably re-open this whenever I manage to work on it. |
|
@arareko no worries! Feel free to reopen, or open a new issue/PR at any time :) |
The module-level add_constructor and add_multi_constructor required handlers that accept any Node and every one of Loader, FullLoader and UnsafeLoader. Since Callable parameters are contravariant, handlers annotated with a specific node class (e.g. SequenceNode) or a single loader class were rejected. Use TypeVars bounded by Node and by the loader union instead. Revert the _N bound change from the first commit of this PR: the union was equivalent to Node and _N is not used by these functions.
|
Hi @AlexWaygood, @JelleZijlstra: as you suggested, I'm back on this. You were right that the |
This comment has been minimized.
This comment has been minimized.
The pyright regression job installs the dependencies of all stubs into one environment. django-stubs depends on types-PyYAML, so pyright resolves yaml to the published stubs instead of the ones in this repository, and the test case fails against the old signatures even though the fix is in place.
|
Dropped the regression test in 2a35889: the pyright test-case job installs |
|
Diff from mypy_primer, showing the effect of this PR on open source code: scipy-stubs (https://github.com/scipy/scipy-stubs)
+ tests/misc/test_submodules_empty.pyi:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
|
|
I'm not sure what the PR in its current state is supposed to fix. It just replaces the concrete types with type vars bound to those types, but the type vars only appear once in each signature, so that's basically a no op. Does the original problem even still apply? Could you provide a short example of the problem using the current stubs? |
|
Yes, it still applies on current import yaml
def _join(loader: yaml.Loader, node: yaml.SequenceNode) -> str:
return ""
yaml.add_constructor("!join", _join)mypy 2.4.0: It isn't a no-op: |
In https://github.com/python/typeshed/blob/294b03f75bd23d95cf4709ba14547cc4190aacdd/stubs/PyYAML/yaml/constructor.pyi the signature for
construct_sequence()definesSequenceNodeas the type for node (which is correct), however the_NTypeVar used in the signature foradd_constructor()only allows forNode.It would seem that
MappingNode,ScalarNodeandSequenceNodeare missing from the TypeVar definition sinceadd_constructor()does not consider any of them as compatible. For example:This PR addresses the above.
Update: retitled from "PyYAML: Add missing types to _N TypeVar". As discussed above, the original
_Nchange didn't address the problem (the union is equivalent toNode, and_Nisn't involved), so the new commit reverts it.The error comes from the module-level
add_constructorandadd_multi_constructorin__init__.pyi. They require handlers that accept anyNodeand all ofLoader | FullLoader | UnsafeLoader, and becauseCallableparameters are contravariant, a handler annotated withSequenceNodeoryaml.Loaderis rejected. They now use TypeVars bounded byNodeand by the loader union.Upstream: https://github.com/yaml/pyyaml/blob/957ae4d495cf8fcb5475c6c2f1bce801096b68a5/lib/yaml/__init__.py#L302