From 0884fe13d471c6b7c5243699a5945d123e334b12 Mon Sep 17 00:00:00 2001 From: Kevin Murphy <53831066+kmurphy4@users.noreply.github.com> Date: Tue, 8 Nov 2022 13:23:47 -0800 Subject: [PATCH] PyYAML: Permit `width: float` for pure-Python `dump(...)` (#8973) * PyYAML: Permit `width: float` for pure-Python `dump(...)` To prevent `PyYAML` from wrapping *any* lines, it's possible to pass `width=float("inf")`, but the current type hints don't like that. This works at runtime: >>> s = yaml.dump({"foo": "bar" * 1000}, width=float("inf")) >>> print(s) foo: barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar... but `mypy` says floatwidth.py:2: error: No overload variant of "dump" matches argument types "Dict[str, str]", "float" floatwidth.py:2: note: Possible overload variants: floatwidth.py:2: note: def dump(data: Any, stream: _WriteStream[Any], Dumper: Any = ..., *, default_style: Optional[str] = ..., default_flow_style: Optional[bool] = ..., canonical: Optional[bool] = ..., indent: Optional[int] = ..., width: Optional[int] = ..., allow_unicode: Optional[bool] = ..., line_break: Optional[str] = ..., encoding: Optional[str] = ..., explicit_start: Optional[bool] = ..., explicit_end: Optional[bool] = ..., version: Optional[Tuple[int, int]] = ..., tags: Optional[Mapping[str, str]] = ..., sort_keys: bool = ...) -> None floatwidth.py:2: note: def dump(data: Any, stream: None = ..., Dumper: Any = ..., *, default_style: Optional[str] = ..., default_flow_style: Optional[bool] = ..., canonical: Optional[bool] = ..., indent: Optional[int] = ..., width: Optional[int] = ..., allow_unicode: Optional[bool] = ..., line_break: Optional[str] = ..., encoding: Optional[str] = ..., explicit_start: Optional[bool] = ..., explicit_end: Optional[bool] = ..., version: Optional[Tuple[int, int]] = ..., tags: Optional[Mapping[str, str]] = ..., sort_keys: bool = ...) -> Any Found 1 error in 1 file (checked 1 source file) Poking through the `PyYAML` source, it looks the `width` parameter could probably be anything "comparable", as it's only compared via the `<` operator[1]. For the LibYAML implementation, however, we have to use `int`s: >>> stream = StringIO() >>> dumper = yaml.CDumper(stream, width=float("inf")) Traceback (most recent call last): File "", line 1, in File "/usr/lib/python3/dist-packages/yaml/cyaml.py", line 81, in __init__ version=version, tags=tags) File "ext/_yaml.pyx", line 973, in _yaml.CEmitter.__init__ (ext/_yaml.c:14797) OverflowError: cannot convert float infinity to integer --- stubs/PyYAML/yaml/__init__.pyi | 27 ++++++++++++++------------- stubs/PyYAML/yaml/dumper.pyi | 11 ++++++++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/stubs/PyYAML/yaml/__init__.pyi b/stubs/PyYAML/yaml/__init__.pyi index 04b68a86a..d3e05fcdd 100644 --- a/stubs/PyYAML/yaml/__init__.pyi +++ b/stubs/PyYAML/yaml/__init__.pyi @@ -7,6 +7,7 @@ from . import resolver as resolver # Help mypy a bit; this is implied by loader from .constructor import BaseConstructor from .cyaml import * from .dumper import * +from .dumper import _Inf from .emitter import _WriteStream from .error import * from .events import * @@ -46,7 +47,7 @@ def emit( Dumper=..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., ): ... @@ -57,7 +58,7 @@ def serialize_all( Dumper=..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -73,7 +74,7 @@ def serialize_all( Dumper=..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -90,7 +91,7 @@ def serialize( *, canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -107,7 +108,7 @@ def serialize( *, canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -125,7 +126,7 @@ def dump_all( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -144,7 +145,7 @@ def dump_all( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -164,7 +165,7 @@ def dump( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -184,7 +185,7 @@ def dump( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -203,7 +204,7 @@ def safe_dump_all( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -222,7 +223,7 @@ def safe_dump_all( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -241,7 +242,7 @@ def safe_dump( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -260,7 +261,7 @@ def safe_dump( default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., diff --git a/stubs/PyYAML/yaml/dumper.pyi b/stubs/PyYAML/yaml/dumper.pyi index 040aa0fed..7203aaeab 100644 --- a/stubs/PyYAML/yaml/dumper.pyi +++ b/stubs/PyYAML/yaml/dumper.pyi @@ -1,5 +1,6 @@ from collections.abc import Mapping from typing import Any +from typing_extensions import TypeAlias from yaml.emitter import Emitter from yaml.representer import BaseRepresenter, Representer, SafeRepresenter @@ -8,6 +9,10 @@ from yaml.serializer import Serializer from .emitter import _WriteStream +# Ideally, there would be a way to limit these values to only +/- float("inf"), +# but that's not possible at the moment (https://github.com/python/typing/issues/1160). +_Inf: TypeAlias = float + class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): def __init__( self, @@ -16,7 +21,7 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -35,7 +40,7 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver): default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ..., @@ -54,7 +59,7 @@ class Dumper(Emitter, Serializer, Representer, Resolver): default_flow_style: bool | None = ..., canonical: bool | None = ..., indent: int | None = ..., - width: int | None = ..., + width: int | _Inf | None = ..., allow_unicode: bool | None = ..., line_break: str | None = ..., encoding: str | None = ...,