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 "<stdin>", line 1, in <module>
      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
This commit is contained in:
Kevin Murphy
2022-11-08 13:23:47 -08:00
committed by GitHub
parent 62a6c3d616
commit 0884fe13d4
2 changed files with 22 additions and 16 deletions

View File

@@ -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 = ...,

View File

@@ -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 = ...,