Skip to content

Commit e48d56c

Browse files
authored
Merge pull request #746 from Zac-HD/multipleOf-overflow
Handle `multipleOf` overflow
2 parents 58259e7 + 46db62a commit e48d56c

File tree

2 files changed

+13
-40
lines changed

2 files changed

+13
-40
lines changed

jsonschema/_validators.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from fractions import Fraction
12
import re
23

34
from jsonschema._utils import (
@@ -166,7 +167,18 @@ def multipleOf(validator, dB, instance, schema):
166167

167168
if isinstance(dB, float):
168169
quotient = instance / dB
169-
failed = int(quotient) != quotient
170+
try:
171+
failed = int(quotient) != quotient
172+
except OverflowError:
173+
# When `instance` is large and `dB` is less than one, quotient can
174+
# overflow to infinity; and then casting to int raises an error.
175+
#
176+
# In this case we fall back to Fraction logic, which is exact and
177+
# cannot overflow. The performance is also acceptable: we try the
178+
# fast all-float option first, and we know that fraction(dB) can have
179+
# at most a few hundred digits in each part. The worst-case slowdown
180+
# is therefore for already-slow enormous integers or Decimals.
181+
failed = (Fraction(instance) / Fraction(dB)).denominator != 1
170182
else:
171183
failed = instance % dB
172184

jsonschema/tests/test_jsonschema_test_suite.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ def missing_date_fromisoformat(test):
161161
DRAFT4.tests(),
162162
DRAFT4.format_tests(),
163163
DRAFT4.optional_tests_of(name="bignum"),
164-
DRAFT4.optional_tests_of(name="float-overflow"),
165164
DRAFT4.optional_tests_of(name="non-bmp-regex"),
166165
DRAFT4.optional_tests_of(name="zeroTerminatedFloats"),
167166
Validator=Draft4Validator,
@@ -235,18 +234,6 @@ def missing_date_fromisoformat(test):
235234
subject="uniqueItems",
236235
description='{"a": true} and {"a": 1} are unique',
237236
)(test)
238-
or skip(
239-
message=bug(743),
240-
subject="float-overflow",
241-
)(test)
242-
or skip(
243-
message=bug(743),
244-
subject="multipleOf",
245-
description=(
246-
"always invalid, but naive implementations "
247-
"may raise an overflow error"
248-
),
249-
)(test)
250237
),
251238
)
252239

@@ -255,7 +242,6 @@ def missing_date_fromisoformat(test):
255242
DRAFT6.tests(),
256243
DRAFT6.format_tests(),
257244
DRAFT6.optional_tests_of(name="bignum"),
258-
DRAFT6.optional_tests_of(name="float-overflow"),
259245
DRAFT6.optional_tests_of(name="non-bmp-regex"),
260246
Validator=Draft6Validator,
261247
format_checker=draft6_format_checker,
@@ -348,18 +334,6 @@ def missing_date_fromisoformat(test):
348334
subject="const",
349335
case_description='const with {"a": true} does not match {"a": 1}',
350336
)(test)
351-
or skip(
352-
message=bug(743),
353-
subject="float-overflow",
354-
)(test)
355-
or skip(
356-
message=bug(743),
357-
subject="multipleOf",
358-
description=(
359-
"always invalid, but naive implementations "
360-
"may raise an overflow error"
361-
),
362-
)(test)
363337
),
364338
)
365339

@@ -368,7 +342,6 @@ def missing_date_fromisoformat(test):
368342
DRAFT7.tests(),
369343
DRAFT7.format_tests(),
370344
DRAFT7.optional_tests_of(name="bignum"),
371-
DRAFT7.optional_tests_of(name="float-overflow"),
372345
DRAFT7.optional_tests_of(name="content"),
373346
DRAFT7.optional_tests_of(name="non-bmp-regex"),
374347
Validator=Draft7Validator,
@@ -484,18 +457,6 @@ def missing_date_fromisoformat(test):
484457
subject="const",
485458
case_description='const with {"a": true} does not match {"a": 1}',
486459
)(test)
487-
or skip(
488-
message=bug(743),
489-
subject="float-overflow",
490-
)(test)
491-
or skip(
492-
message=bug(743),
493-
subject="multipleOf",
494-
description=(
495-
"always invalid, but naive implementations "
496-
"may raise an overflow error"
497-
),
498-
)(test)
499460
),
500461
)
501462

0 commit comments

Comments
 (0)