From 95ebea2ba64140762115920626857e36b5ce4fca Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Tue, 10 Nov 2026 12:45:59 +0000 Subject: [PATCH 1/3] scripts/repo_shape.py: a plain decimal with a nonzero digit that is too small for a 64-bit float, `0.` and four hundred `0`s and a `1`, is `yaml-unparsable` by its line with the large end's remedy, where `_scalar` read it as `0.0` and `check` and `execute` went on with a number the file does not hold (#1260) `_scalar` read a plain decimal with `float()` and refused only the result that is infinite (#1212, PR #1249). A decimal that holds a nonzero digit and whose float is zero changes kind the same way at the small end, from nonzero to zero, so it now raises the same `YamlError` with `_UNMADE_NUMBER_REMEDY`, in words that say it would be zero where the large end's say it would be infinite: `a plain decimal of 402 digits is too small to read as a number: a 64-bit float cannot hold it, so it would be zero`. `load_yaml` names the line, and `check` and `execute` print the refusal and exit 2 with no traceback, in a `commit:`, a key outside `pins:` and a `follow_ups:` item. The test of a nonzero digit asks each digit its value, because the pattern takes the digits of every script and `float()` reads each as its value. `0.0`, `-0.0`, a decimal of only zeros and a subnormal such as 5e-324 (326 characters) are numbers still. `adopt-project.py` needs no change: the refused value never reaches `_read_as`. Rows are in tests/test_plan_number_limits.py, 27 of them. Lane 3's ruling is #1260 issuecomment-6767326422. Stacked on #1249 (for #1212) at 3e5d1fde1. Co-Authored-By: Claude Sonnet 5.5 --- scripts/repo_shape.py | 35 +++++-- tests/test_plan_number_limits.py | 164 ++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 10 deletions(-) diff --git a/scripts/repo_shape.py b/scripts/repo_shape.py index 123595ef..6b0cd7b0 100644 --- a/scripts/repo_shape.py +++ b/scripts/repo_shape.py @@ -189,10 +189,10 @@ class YamlError(Exception): `line` AND `remediation` ARE FOR `load_yaml`, WHICH NAMES A FILE (#708). Where the fix is one edit of the value, the same in every file, the refusal carries it (`_indicator_refusal`, and `_scalar`'s for a number - it cannot make, #1212); every other refusal carries none. Such a - refusal is raised where the value is read, which knows no line, so the - block reader records the line it read the value on (`_block_value`), - and `load_yaml` names it. It stays out of the words: + it cannot make, #1212 and #1260); every other refusal carries none. + Such a refusal is raised where the value is read, which knows no line, + so the block reader records the line it read the value on + (`_block_value`), and `load_yaml` names it. It stays out of the words: a tool that asks the reader about ONE rendered line (`k: @a`) quotes those words in a sentence of its own, where `line 1:` would be noise. """ @@ -227,8 +227,9 @@ def __init__(self, message: str, remediation: str = ""): # integer of more digits than `int()` takes (`sys.get_int_max_str_digits()`, # 4300 by default), which ended every tool in a `ValueError` traceback, and # a decimal too large for a 64-bit float to hold, which was read as the float -# `inf`, a number this reader reads no plain scalar as (`inf` is text). See -# `_scalar`. +# `inf`, a number this reader reads no plain scalar as (`inf` is text). The +# other end is refused the same way (#1260): a decimal with a nonzero digit +# that a 64-bit float can only make `0.0` of. See `_scalar`. # # A BLOCK SCALAR'S BODY IS READ AS YAML READS IT, OR REFUSED BY ITS LINE # (#1004). `+` keeps the empty lines at the block's end, where it was read @@ -623,6 +624,16 @@ def _scalar(raw: str) -> Any: second "the number inf". The value can be thousands of characters long, so the refusal says how many digits it holds, and `load_yaml` names its line. + + THE OTHER END IS REFUSED THE SAME WAY (#1260): a decimal that holds a + nonzero digit and whose float is zero (`0.` and four hundred `0`s and a + `1`), which was read as `0.0`, a number the file does not hold. It + changes kind as the large end does, from nonzero to zero, where rounding + keeps the kind: a subnormal such as 5e-324 is nonzero, so it is a number + still, and so are `0.0`, `-0.0` and a decimal of only zeros. The test of + a nonzero digit asks each digit its value and does not look for `1` to + `9`, because the pattern above takes the digits of every script and + `float()` reads each as its value. """ text = raw.strip(_YAML_WHITE) if text == "" or text in ("null", "~", "Null", "NULL"): @@ -651,6 +662,12 @@ def _scalar(raw: str) -> Any: "digits is too large to read as a number: a " "64-bit float cannot hold it, so it would be " "infinite", _UNMADE_NUMBER_REMEDY) + if number == 0.0 and any( + int(digit) for digit in text.lstrip("-").replace(".", "")): + raise YamlError(f"a plain decimal of {len(text.lstrip('-')) - 1} " + "digits is too small to read as a number: a " + "64-bit float cannot hold it, so it would be " + "zero", _UNMADE_NUMBER_REMEDY) return number return text @@ -1308,9 +1325,9 @@ def _block_value(text: str, line: int) -> Any: open with a backtick ...`, among the hundreds of lines a plan holds. The line is recorded on the refusal (`YamlError.line`), never put in its words, where the refusal carries a remedy (`_indicator_refusal`'s, - or `_UNMADE_NUMBER_REMEDY`, #1212): one that tells a person to edit a - value says where it is. The others keep the words they had, which the - naming gate's `declared-unverified` reason and the root's + or `_UNMADE_NUMBER_REMEDY`, #1212 and #1260): one that tells a person to + edit a value says where it is. The others keep the words they had, which + the naming gate's `declared-unverified` reason and the root's `validate-pins.py` print, and tests quote, whole. """ try: diff --git a/tests/test_plan_number_limits.py b/tests/test_plan_number_limits.py index 180e427a..f81e6805 100644 --- a/tests/test_plan_number_limits.py +++ b/tests/test_plan_number_limits.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 """A plain number the plan's reader cannot make is refused by its line, and a float it does make is said in digits a plan can hold (#1212, which follows -#1114 and #1198). +#1114 and #1198), at the small end of a decimal as at the large (#1260). RV1198 found both on #1198, and both are older than it. @@ -19,6 +19,14 @@ `load_yaml` names the line; and `_read_as` says a float in the digits of its `repr`, written out with no exponent, which the reader reads back as it. +#1260 is the other end of a decimal. `float()` makes `0.0` of a plain decimal +that holds a nonzero digit and is too small for a 64-bit float (`0.` and four +hundred `0`s and a `1`), a number the file does not hold, where it makes +`inf` of one too large. `_scalar` refuses it as it refuses that one: the same +`yaml-unparsable` by its line, with the same remedy, in words that say it +would be zero. `0.0`, `-0.0`, a decimal of only zeros and a subnormal such as +5e-324 are numbers still. + The reader's rows run in this process. The plan's rows edit a plan `plan` wrote and run `check` and `execute --yes` on it, with a stub `gh` first on PATH and `--local-remote-dir`: neither asks `gh` anything or makes the @@ -62,6 +70,22 @@ LONGEST = "1" * DEFAULT_DIGITS INFINITE = "1" * 400 + ".5" +#: W1212's decimal that is too small: `0.`, four hundred `0`s and a `1`. +#: `float()` makes `0.0` of it, a number nothing in the file holds. +TINY = "0." + "0" * 400 + "1" + +#: The decimals a digit either side of half the smallest float, 5e-324, which +#: `float()` rounds to the nearer of 0.0 and 5e-324: the one under half is +#: `0.0`, so it is refused, and the one over half is 5e-324, a number. +BELOW_HALF = "0." + "0" * 323 + "24703282292062327" +ABOVE_HALF = "0." + "0" * 323 + "24703282292062328" + +#: Arabic-Indic zero and one: the pattern `_scalar` reads a decimal by takes +#: the digits of every script, and `float()` reads each as its value. Escapes, +#: so that this file stays ASCII. +ZERO_OF_ANOTHER_SCRIPT = "\u0660" +ONE_OF_ANOTHER_SCRIPT = "\u0661" + def too_long(digits: int) -> str: return (f"a plain integer of {digits} digits is too long for this Python " @@ -73,6 +97,11 @@ def too_large(digits: int) -> str: "number: a 64-bit float cannot hold it, so it would be infinite") +def too_small(digits: int) -> str: + return (f"a plain decimal of {digits} digits is too small to read as a " + "number: a 64-bit float cannot hold it, so it would be zero") + + needs_the_setting = pytest.mark.skipif( not hasattr(sys, "set_int_max_str_digits"), reason="this Python has no limit on an integer's digits") @@ -176,6 +205,73 @@ def test_the_refusal_follows_this_pythons_setting(tmp_path, default_digits): assert parse_yaml(f"k: {LONG}\n") == {"k": int(LONG)} +# --- the small end: a decimal a float can only make zero of (#1260) ---------- + +#: `(the file, the line the number is on, how many digits it holds)`, by test +#: id: W1212's decimal and the same with a minus sign, in each shape a plain +#: value is read in, and the two edges: the decimal a digit under half the +#: smallest float, and one in the digits of another script. Every one has a +#: nonzero digit and a float of zero. +TOO_SMALL = { + "block-value": (f"a: 1\nk: {TINY}\n", 2, 402), + "block-value-negative": (f"a: 1\nk: -{TINY}\n", 2, 402), + "sequence-item": (f"a: 1\nk:\n - {TINY}\n", 3, 402), + "sequence-item-negative": (f"a: 1\nk:\n - -{TINY}\n", 3, 402), + "flow-sequence": (f"a: 1\nk: [1.5, {TINY}]\n", 2, 402), + "flow-sequence-negative": (f"a: 1\nk: [1.5, -{TINY}]\n", 2, 402), + "flow-mapping": (f"a: 1\nk: {{x: {TINY}}}\n", 2, 402), + "flow-mapping-negative": (f"a: 1\nk: {{x: -{TINY}}}\n", 2, 402), + "nested": (f"a:\n b:\n k: {TINY}\n", 3, 402), + "nested-negative": (f"a:\n b:\n k: -{TINY}\n", 3, 402), + "below-half-the-smallest": (f"k: {BELOW_HALF}\n", 1, 341), + "another-script": ( + f"k: 0.{ZERO_OF_ANOTHER_SCRIPT * 400}{ONE_OF_ANOTHER_SCRIPT}\n", 1, + 402), +} + + +@pytest.mark.parametrize("case", sorted(TOO_SMALL)) +def test_a_decimal_a_float_can_only_make_zero_of_is_refused_by_its_line( + tmp_path, case): + """`yaml-unparsable`, naming the file and the line, with the remedy and + words that say it would be zero, as the large end's say it would be + infinite: in every place a plain value is read, with a minus sign or + none, and where the digits are another script's.""" + text, line, digits = TOO_SMALL[case] + refusal = refusal_of(tmp_path, text) + assert refusal.code == "yaml-unparsable" + assert refusal.detail == ( + f"{tmp_path / 'file.yaml'}: line {line}: {too_small(digits)}"), ( + refusal.detail) + assert refusal.remediation == REMEDY + assert isinstance(refusal.__cause__, YamlError) + + +#: `(the decimal, what the reader makes of it)`, by test id: the controls. +#: A decimal of only zeros, in either script and either sign, is a number +#: with no nonzero digit; 5e-324 is a nonzero float, spelled in its 326 +#: characters, and so is the decimal a digit over half of it. +STILL_NUMBERS = { + "zero": ("0.0", 0.0), + "negative-zero": ("-0.0", -0.0), + "zeros": ("0.000", 0.0), + "many-zeros": ("0." + "0" * 400, 0.0), + "many-zeros-negative": ("-0." + "0" * 400, -0.0), + "zeros-of-another-script": ( + f"{ZERO_OF_ANOTHER_SCRIPT}.{ZERO_OF_ANOTHER_SCRIPT * 400}", 0.0), + "the-smallest": ("0." + "0" * 323 + "5", 5e-324), + "the-smallest-negative": ("-0." + "0" * 323 + "5", -5e-324), + "above-half-the-smallest": (ABOVE_HALF, 5e-324), +} + + +@pytest.mark.parametrize("case", sorted(STILL_NUMBERS)) +def test_a_decimal_a_float_can_hold_is_still_read_as_a_number(case): + """`repr` of the whole, so that a `-0.0` read as `0.0` is not the same.""" + spelled, value = STILL_NUMBERS[case] + assert repr(parse_yaml(f"k: {spelled}\n")) == repr({"k": value}) + + # --- `_read_as`: a float in digits the reader reads back as it -------------- @@ -290,6 +386,72 @@ def test_a_commit_too_large_to_be_finite_is_refused_by_its_line( too_large(401)) +# --- the small end, through `check` and `execute` (#1260) ------------------- + + +@pytest.mark.parametrize("sign", ["", "-"], ids=["positive", "negative"]) +def test_a_commit_too_small_to_be_nonzero_is_refused_by_its_line( + answered, tmp_path, sign): + """`check` and `execute` read W1212's decimal in a `commit:` as "the + number 0.0" and said it was not text; they now refuse it, by its line, as + they refuse one too large to be finite.""" + raw = sign + TINY + text = pinned(answered, a_pin(commit=raw)) + refused_unparsable(text, tmp_path, line_of(text, f" commit: {raw}"), + too_small(402)) + + +def test_a_key_outside_pins_too_small_to_be_nonzero_is_refused_by_its_line( + tmp_path): + """A key no pin holds was read as `0.0`, and the plan was a good one: + `check` printed no finding, and `execute` made the legs. It is the + reader's fault, not the pin rows', so it is refused the same way. + + The row makes a source of its own, not the module's: where the reader + read it as `0.0`, `execute` ran the plan and left its split branch in the + source, and every row after this one would find `adopt-branch-exists`.""" + own = tmp_path / "own" + own.mkdir() + planned_text = planned(make_source_repo(own / "Thing"), own, + dict(ANSWERS)).read_text(encoding=UTF8) + text = planned_text + f"probe_extra: {TINY}\n" + refused_unparsable(text, tmp_path, len(text.splitlines()), too_small(402)) + + +def test_a_follow_up_too_small_to_be_nonzero_is_refused_by_its_line( + answered, tmp_path): + """A `follow_ups:` item was read as `0.0` and `check` found it is a + number, not text; the reader refuses it first.""" + assert answered.count("\nfollow_ups:\n") == 1 + text = answered.replace("\nfollow_ups:\n", + "\nfollow_ups:\n - " + TINY + "\n", 1) + refused_unparsable(text, tmp_path, line_of(text, f" - {TINY}"), + too_small(402)) + + +#: `(the commit as the plan spells it, how the finding says it)`, by test +#: id: decimals a float can hold, which are numbers still, and so are said. +HELD = { + "zeros": ("0." + "0" * 400, "0.0"), + "the-smallest": ("0." + "0" * 323 + "5", "0." + "0" * 323 + "5"), +} + + +@needs_filter_repo +@pytest.mark.parametrize("case", sorted(HELD)) +def test_a_commit_a_float_can_hold_is_still_a_finding(answered, tmp_path, + case): + """The controls: a decimal of only zeros and the smallest float are + numbers, and the `commit:` is said as #1198 says one that is not text.""" + raw, digits = HELD[case] + found = one_finding(answered, tmp_path, (a_pin(commit=raw),), + "plan-pin-malformed") + assert found.startswith( + f"FINDING plan-pin-malformed: {ENTRY_NAMED} records `commit:` as the " + f"number {digits}, which is not text. {FROM}, and nothing else: "), ( + found[:400]) + + @needs_filter_repo def test_a_commit_of_4300_digits_is_still_a_finding(answered, tmp_path, default_digits): From b44c8c8f3dc508b2d953fbbfa18f2a45177ad078 Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Tue, 10 Nov 2026 16:18:53 +0000 Subject: [PATCH 2/3] tests/test_plan_number_limits.py: a nonzero digit that is not the last is refused too, at the default digit limit (#1260) RV1309's review of #1309 found that in every refused decimal the rows use, the nonzero digit is the last character, so two rewrites of the check in `_scalar` passed all 62 rows: one that tests only the last digit, which reads `0.`, 400 `0`s and `10` as `0.0`, and one that makes one `int()` of all the digits, which raises an uncaught `ValueError` past 4300 digits. Two rows, `nonzero-digit-not-last` and `nonzero-digit-not-last-negative` (`0.`, 4400 `0`s and `10`, 4403 digits), join `TOO_SMALL`. The refusal row takes the `default_digits` fixture, so it reads at 4300 digits on a host whose limit is 640 or 0 as on any other. Each row fails under both rewrites. No code changes. Co-Authored-By: Claude Sonnet 5.5 --- tests/test_plan_number_limits.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/test_plan_number_limits.py b/tests/test_plan_number_limits.py index f81e6805..01d11efd 100644 --- a/tests/test_plan_number_limits.py +++ b/tests/test_plan_number_limits.py @@ -209,9 +209,12 @@ def test_the_refusal_follows_this_pythons_setting(tmp_path, default_digits): #: `(the file, the line the number is on, how many digits it holds)`, by test #: id: W1212's decimal and the same with a minus sign, in each shape a plain -#: value is read in, and the two edges: the decimal a digit under half the -#: smallest float, and one in the digits of another script. Every one has a -#: nonzero digit and a float of zero. +#: value is read in, and the three edges: the decimal a digit under half the +#: smallest float, one in the digits of another script, and one whose nonzero +#: digit is not the last, with more digits than the default limit lets +#: `int()` read in one piece (a test of the last digit alone, or of all the +#: digits as one integer, reads that one wrong). Every one has a nonzero digit +#: and a float of zero. TOO_SMALL = { "block-value": (f"a: 1\nk: {TINY}\n", 2, 402), "block-value-negative": (f"a: 1\nk: -{TINY}\n", 2, 402), @@ -227,16 +230,20 @@ def test_the_refusal_follows_this_pythons_setting(tmp_path, default_digits): "another-script": ( f"k: 0.{ZERO_OF_ANOTHER_SCRIPT * 400}{ONE_OF_ANOTHER_SCRIPT}\n", 1, 402), + "nonzero-digit-not-last": (f"k: 0.{'0' * 4400}10\n", 1, 4403), + "nonzero-digit-not-last-negative": (f"k: -0.{'0' * 4400}10\n", 1, 4403), } @pytest.mark.parametrize("case", sorted(TOO_SMALL)) def test_a_decimal_a_float_can_only_make_zero_of_is_refused_by_its_line( - tmp_path, case): + tmp_path, default_digits, case): """`yaml-unparsable`, naming the file and the line, with the remedy and words that say it would be zero, as the large end's say it would be infinite: in every place a plain value is read, with a minus sign or - none, and where the digits are another script's.""" + none, where the digits are another script's, and where the nonzero digit + is not the last: read at Python's default limit on an integer's digits, + whatever this host's setting is.""" text, line, digits = TOO_SMALL[case] refusal = refusal_of(tmp_path, text) assert refusal.code == "yaml-unparsable" From 574a8a7a25171413b072164b5cda3d39db50ae83 Mon Sep 17 00:00:00 2001 From: Brett Heap Date: Tue, 10 Nov 2026 16:38:20 +0000 Subject: [PATCH 3/3] scripts/repo_shape.py: a decimal's zero test reads its float as falsy and moves into _plain_decimal, and a nonzero digit far from the end is refused too (#1260) SonarCloud read #1309's own code as a float equality (S1244, the reliability bug that turns its gate red) and as a function of cognitive complexity 17 where 15 is allowed (S3776). scripts/repo_shape.py: the decimal branch of `_scalar` is now `_plain_decimal(text)`, beside it: the `inf` refusal, the zero refusal and the return, with no message, remedy, order of tests or exception type changed. Its zero test is `not number`, which is true of exactly 0.0 and -0.0, and a comment says so. `_scalar` counts 12 by SonarSource's rules (17 before) and the helper 3. tests/test_plan_number_limits.py: `nonzero-digit-then-many-zeros` and its `-negative` twin, `0.`, 323 zeros, a `1` and 4400 zeros (4725 digits). A test of only the last few digits read both as zero and passed every earlier row (RVD1309's NIT-1). Co-Authored-By: Claude Sonnet 5.5 --- scripts/repo_shape.py | 35 ++++++++++++++++++++------------ tests/test_plan_number_limits.py | 14 +++++++++---- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/scripts/repo_shape.py b/scripts/repo_shape.py index 6b0cd7b0..3d8c847d 100644 --- a/scripts/repo_shape.py +++ b/scripts/repo_shape.py @@ -599,6 +599,27 @@ def _indicator_refusal(text: str) -> YamlError: "run the command again.") +def _plain_decimal(text: str) -> float: + """The float of the plain decimal `text` that `_scalar` read, refused + where a 64-bit float cannot hold it: infinite (#1212) or zero with a + nonzero digit (#1260). `_scalar`'s docstring says why.""" + number = float(text) + if math.isinf(number): + raise YamlError(f"a plain decimal of {len(text.lstrip('-')) - 1} " + "digits is too large to read as a number: a " + "64-bit float cannot hold it, so it would be " + "infinite", _UNMADE_NUMBER_REMEDY) + # A float is falsy exactly when it is 0.0 or -0.0: the pattern makes no + # nan and inf is refused above, so `not number` asks whether it is zero. + if not number and any( + int(digit) for digit in text.lstrip("-").replace(".", "")): + raise YamlError(f"a plain decimal of {len(text.lstrip('-')) - 1} " + "digits is too small to read as a number: a " + "64-bit float cannot hold it, so it would be " + "zero", _UNMADE_NUMBER_REMEDY) + return number + + def _scalar(raw: str) -> Any: """One scalar's value: null, a quoted scalar's text, a bool, a number, or a plain scalar's text. @@ -656,19 +677,7 @@ def _scalar(raw: str) -> Any: "digits is too long for this Python to read as a " "number", _UNMADE_NUMBER_REMEDY) from exc if re.fullmatch(r"-?\d+\.\d+", text): - number = float(text) - if math.isinf(number): - raise YamlError(f"a plain decimal of {len(text.lstrip('-')) - 1} " - "digits is too large to read as a number: a " - "64-bit float cannot hold it, so it would be " - "infinite", _UNMADE_NUMBER_REMEDY) - if number == 0.0 and any( - int(digit) for digit in text.lstrip("-").replace(".", "")): - raise YamlError(f"a plain decimal of {len(text.lstrip('-')) - 1} " - "digits is too small to read as a number: a " - "64-bit float cannot hold it, so it would be " - "zero", _UNMADE_NUMBER_REMEDY) - return number + return _plain_decimal(text) return text diff --git a/tests/test_plan_number_limits.py b/tests/test_plan_number_limits.py index 01d11efd..ef1b0afe 100644 --- a/tests/test_plan_number_limits.py +++ b/tests/test_plan_number_limits.py @@ -210,10 +210,12 @@ def test_the_refusal_follows_this_pythons_setting(tmp_path, default_digits): #: `(the file, the line the number is on, how many digits it holds)`, by test #: id: W1212's decimal and the same with a minus sign, in each shape a plain #: value is read in, and the three edges: the decimal a digit under half the -#: smallest float, one in the digits of another script, and one whose nonzero +#: smallest float, one in the digits of another script, one whose nonzero #: digit is not the last, with more digits than the default limit lets #: `int()` read in one piece (a test of the last digit alone, or of all the -#: digits as one integer, reads that one wrong). Every one has a nonzero digit +#: digits as one integer, reads that one wrong), and one whose nonzero digit +#: has thousands of zeros after it and hundreds before it (a test of only +#: the last few digits reads that one wrong). Every one has a nonzero digit #: and a float of zero. TOO_SMALL = { "block-value": (f"a: 1\nk: {TINY}\n", 2, 402), @@ -232,6 +234,10 @@ def test_the_refusal_follows_this_pythons_setting(tmp_path, default_digits): 402), "nonzero-digit-not-last": (f"k: 0.{'0' * 4400}10\n", 1, 4403), "nonzero-digit-not-last-negative": (f"k: -0.{'0' * 4400}10\n", 1, 4403), + "nonzero-digit-then-many-zeros": ( + f"k: 0.{'0' * 323}1{'0' * 4400}\n", 1, 4725), + "nonzero-digit-then-many-zeros-negative": ( + f"k: -0.{'0' * 323}1{'0' * 4400}\n", 1, 4725), } @@ -242,8 +248,8 @@ def test_a_decimal_a_float_can_only_make_zero_of_is_refused_by_its_line( words that say it would be zero, as the large end's say it would be infinite: in every place a plain value is read, with a minus sign or none, where the digits are another script's, and where the nonzero digit - is not the last: read at Python's default limit on an integer's digits, - whatever this host's setting is.""" + is not the last, or is followed by thousands of zeros: read at Python's + default limit on an integer's digits, whatever this host's setting is.""" text, line, digits = TOO_SMALL[case] refusal = refusal_of(tmp_path, text) assert refusal.code == "yaml-unparsable"