Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Added `message` to `JsonSchemaValuesException` joining messages of all collected errors
* Fixed the `date-time` format accepting months, days and hours out of range (such as `2020-19-39T29:00:00Z`) and rejecting a leap second (`23:59:60Z`)
* Fixed the `time` format accepting hours, minutes, seconds and offsets out of range (such as `29:99:99`)
* Fixed `minimum` and `maximum` being exclusive in draft 06 and later when `exclusiveMinimum` or `exclusiveMaximum` is set to a number other than zero

=== 2.22.2 (2026-08-15)

Expand Down
22 changes: 22 additions & 0 deletions fastjsonschema/draft06.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,28 @@ def generate_type(self):
with self.l('if not isinstance({variable}, ({})){}:', python_types, extra):
self.exc('{name} must be {}', ' or '.join(types), rule='type')

def generate_minimum(self):
"""
Since draft 06 exclusiveMinimum is a number validated on its own,
so minimum is always inclusive.
"""
with self.l('if isinstance({variable}, (int, float, Decimal)) and not isinstance({variable}, bool):'):
if not isinstance(self._definition['minimum'], (int, float, decimal.Decimal)):
raise JsonSchemaDefinitionException('minimum must be a number')
with self.l('if {variable} < {minimum}:'):
self.exc('{name} must be bigger than or equal to {minimum}', rule='minimum')

def generate_maximum(self):
"""
Since draft 06 exclusiveMaximum is a number validated on its own,
so maximum is always inclusive.
"""
with self.l('if isinstance({variable}, (int, float, Decimal)) and not isinstance({variable}, bool):'):
if not isinstance(self._definition['maximum'], (int, float, decimal.Decimal)):
raise JsonSchemaDefinitionException('maximum must be a number')
with self.l('if {variable} > {maximum}:'):
self.exc('{name} must be smaller than or equal to {maximum}', rule='maximum')

def generate_exclusive_minimum(self):
with self.l('if isinstance({variable}, (int, float, Decimal)) and not isinstance({variable}, bool):'):
if not isinstance(self._definition['exclusiveMinimum'], (int, float, decimal.Decimal)):
Expand Down
15 changes: 15 additions & 0 deletions tests/test_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,21 @@ def test_exclusive_numeric_keywords_ignore_boolean(asserter, schema_version, key
}, value, value)


@pytest.mark.parametrize('schema_version', (
'http://json-schema.org/draft-06/schema',
'http://json-schema.org/draft-07/schema',
))
@pytest.mark.parametrize('keywords', (
{'minimum': 10, 'exclusiveMinimum': 5},
{'maximum': 10, 'exclusiveMaximum': 15},
))
def test_minimum_and_maximum_stay_inclusive_next_to_exclusive_keywords(asserter, schema_version, keywords):
asserter({
'$schema': schema_version,
**keywords,
}, 10, 10)


@pytest.mark.parametrize('value', (
1.0,
0.1,
Expand Down