fix: align std.format edge cases with Python#1078
Open
He-Pin wants to merge 1 commit into
Open
Conversation
7149c61 to
fe86128
Compare
30b5903 to
1ad170b
Compare
Motivation: Jsonnet documents std.format and the % string operator as following Python-style formatting rules. sjsonnet diverged on several edge cases: floating-point formats did not preserve the IEEE -0.0 sign bit, dynamic * width/precision accepted fractional values via truncation, negative dynamic width/precision did not consistently follow Python behavior, %s ignored precision, and %g exponent selection was sensitive to floating-point log10 roundoff. Modification: Normalize dynamic * width and precision through a shared Python-style integer conversion path, including negative width and negative precision handling. Preserve -0.0 signs for floating-point conversions, keep integral conversions unchanged, apply %s precision by Jsonnet codepoint, and stabilize %g exponent calculation around powers of ten. Add focused regression coverage for negative zero, dynamic * width/precision, fractional * errors, %s precision, and %g boundary values. Result: sjsonnet follows the official std.format Python-style contract for these formatting edge cases. The PR is format-only and no longer includes unrelated manifestXmlJsonml changes. References: https://jsonnet.org/ref/stdlib.html#std-format https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting
1ad170b to
45eaea8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation:
The official
std.format(str, vals)documentation says string formatting follows the same rules as Python, and that the%operator is shorthand forstd.format:https://jsonnet.org/ref/stdlib.html#std-format
sjsonnet diverged from those Python-style rules in several formatting edge cases:
-0.0to positive zero for%f,%e,%g, and%G*width/precision silently accepted fractional Jsonnet numbers through truncation%behavior%signored precision, including dynamic precision from*%gexponent selection around powers of ten was sensitive to floating-pointlog10roundoffModification:
This change keeps
std.formatanchored to the official Python-style contract instead of treating any single implementation as the specification.-0.0for floating-point conversions while leaving integer conversions unchanged.*width and precision through a shared helper:*must be finite whole-number values.%gthen maps precision zero to one as Python does.%sprecision by Jsonnet codepoint before width padding.%gexponent selection around powers of ten by compensating for smalllog10floating-point error.%gboundary values, dynamic*width/precision,%sprecision, and fractional*errors.Result:
sjsonnet now matches Python
%behavior for the coveredstd.formatedge cases. The table below includes the old sjsonnet behavior frommasterbefore this PR.%"%+f" % (-0.0)"-0.000000""+0.000000""-0.000000""+0.000000""+0.000000""%f" % (-0.0)"-0.000000""0.000000""-0.000000""0.000000""0.000000""%g" % (-0.0)"-0""0""-0""0""0e-00""%g" % 0.0001"0.0001""0.0001""0.0001""0.0001""0.0""%*g" % [-4, 1.0]"1 ""1""1 ""1""1""%.*g" % [-3, 1.23456]"1"Internal Error, caused by/ by zero"1""5001e+00""%.*s" % [-3, "abcdef"]"""abcdef""""abcdef""abcdef""%.1s" % "😀x""😀""😀x""😀""😀x""😀x""%*g" % [3.7, 1.0]TypeError: * wants int" 1"" 1"" 1""%.*g" % [2.7, 1.23456]TypeError: * wants int"1.2""1.11.8812766372727552""1.2"The PR is now a single format-only commit and no longer includes unrelated
manifestXmlJsonmlchanges.References:
std.formatdocumentation: https://jsonnet.org/ref/stdlib.html#std-format