summaryrefslogtreecommitdiff
path: root/jsonschema/_format.py
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2021-08-04 10:58:09 +0100
committerJulian Berman <Julian@GrayVines.com>2021-08-04 10:58:09 +0100
commit1a7a935fd3e4dc11089b0a9f6ac247d66dc6b358 (patch)
tree9ab27da280b462ac59510a715658a687c125a771 /jsonschema/_format.py
parent72a0c608f030a70c431dd1632e13d04e7370edff (diff)
parent4547b2ab8a74dd8a83c9104606b2166a9e712fa2 (diff)
downloadjsonschema-1a7a935fd3e4dc11089b0a9f6ac247d66dc6b358.tar.gz
Merge remote-tracking branch 'anexia-it/draft2020-12'
* anexia-it/draft2020-12: Julian/jsonschema#782: Remove ecmascript validation, extend dynamicRef skip description Julian/jsonschema#782: Add compatibility to draft7 and older Julian/jsonschema#782: Code clenaup, fixes validation messages Julian/jsonschema#782: Extend format tests Julian/jsonschema#782: Resolve meta schema vocabularies from local cache Julian/jsonschema#782: Refactor items behavior with prefixItems Julian/jsonschema#782: Update validation message for unevaluatedProperties and unevaluatedItems Julian/jsonschema#782: Fixes failing styles Julian/jsonschema#782: Adapt validator test for draft2020-12, fixes code styles Julian/jsonschema#782: Fixes relative json pointer format validation for leading zero on digit Julian/jsonschema#782: Load dependencies from legacy validators Julian/jsonschema#782: Implements dynamicRef validations Julian/jsonschema#782: Add validation for uuid format Julian/jsonschema#782: Implements defs validations Julian/jsonschema#782: Extend resolver for anchor Julian/jsonschema#782: Fixes ref resolver for folders Julian/jsonschema#782: Fixes ref validation priority Julian/jsonschema#782: Extend implementation of ref Julian/jsonschema#782: Implements unevaluatedProperties validations Julian/jsonschema#782: Implements unevaluatedItems validations Julian/jsonschema#782: Extend contains with minContains and maxContaints, add contains legacy validator Julian/jsonschema#782: Adapt items to work with prefixItems Julian/jsonschema#782: Add checks for prefixItems, basic check for unevaluatedItems Julian/jsonschema#782: Extend format check for draft2020-12, add duration format check Julian/jsonschema#782: Add dependentRequired and dependentSchemas validation Julian/jsonschema#782: Split format and regular test cases on draft2020-12 Julian/jsonschema#782: Enable draft2020-12 test suite
Diffstat (limited to 'jsonschema/_format.py')
-rw-r--r--jsonschema/_format.py84
1 files changed, 75 insertions, 9 deletions
diff --git a/jsonschema/_format.py b/jsonschema/_format.py
index bdd893d..19f4283 100644
--- a/jsonschema/_format.py
+++ b/jsonschema/_format.py
@@ -1,3 +1,4 @@
+from uuid import UUID
import datetime
import ipaddress
import re
@@ -131,13 +132,14 @@ draft3_format_checker = FormatChecker()
draft4_format_checker = FormatChecker()
draft6_format_checker = FormatChecker()
draft7_format_checker = FormatChecker()
-
+draft202012_format_checker = FormatChecker()
_draft_checkers = dict(
draft3=draft3_format_checker,
draft4=draft4_format_checker,
draft6=draft6_format_checker,
draft7=draft7_format_checker,
+ draft202012=draft202012_format_checker,
)
@@ -147,12 +149,14 @@ def _checks_drafts(
draft4=None,
draft6=None,
draft7=None,
+ draft202012=None,
raises=(),
):
draft3 = draft3 or name
draft4 = draft4 or name
draft6 = draft6 or name
draft7 = draft7 or name
+ draft202012 = draft202012 or name
def wrap(func):
if draft3:
@@ -163,13 +167,17 @@ def _checks_drafts(
func = _draft_checkers["draft6"].checks(draft6, raises)(func)
if draft7:
func = _draft_checkers["draft7"].checks(draft7, raises)(func)
+ if draft202012:
+ func = _draft_checkers["draft202012"].checks(
+ draft202012, raises
+ )(func)
# Oy. This is bad global state, but relied upon for now, until
# deprecation. See https://github.com/Julian/jsonschema/issues/519
# and test_format_checkers_come_with_defaults
- FormatChecker.cls_checks(draft7 or draft6 or draft4 or draft3, raises)(
- func,
- )
+ FormatChecker.cls_checks(
+ draft202012 or draft7 or draft6 or draft4 or draft3, raises
+ )(func)
return func
return wrap
@@ -187,6 +195,7 @@ def is_email(instance):
draft4="ipv4",
draft6="ipv4",
draft7="ipv4",
+ draft202012="ipv4",
raises=ipaddress.AddressValueError,
)
def is_ipv4(instance):
@@ -213,6 +222,7 @@ else:
draft4="hostname",
draft6="hostname",
draft7="hostname",
+ draft202012="hostname",
)
def is_host_name(instance):
if not isinstance(instance, str):
@@ -228,6 +238,7 @@ except ImportError: # pragma: no cover
else:
@_checks_drafts(
draft7="idn-hostname",
+ draft202012="idn-hostname",
raises=(idna.IDNAError, UnicodeError),
)
def is_idn_host_name(instance):
@@ -254,6 +265,7 @@ except ImportError:
@_checks_drafts(
draft6="uri-reference",
draft7="uri-reference",
+ draft202012="uri-reference",
raises=ValueError,
)
def is_uri_reference(instance):
@@ -262,19 +274,30 @@ except ImportError:
return validate_rfc3986(instance, rule="URI_reference")
else:
- @_checks_drafts(draft7="iri", raises=ValueError)
+ @_checks_drafts(
+ draft7="iri",
+ draft202012="iri",
+ raises=ValueError,
+ )
def is_iri(instance):
if not isinstance(instance, str):
return True
return rfc3987.parse(instance, rule="IRI")
- @_checks_drafts(draft7="iri-reference", raises=ValueError)
+ @_checks_drafts(
+ draft7="iri-reference",
+ draft202012="iri-reference",
+ raises=ValueError,
+ )
def is_iri_reference(instance):
if not isinstance(instance, str):
return True
return rfc3987.parse(instance, rule="IRI_reference")
- @_checks_drafts(name="uri", raises=ValueError)
+ @_checks_drafts(
+ name="uri",
+ raises=ValueError,
+ )
def is_uri(instance):
if not isinstance(instance, str):
return True
@@ -283,6 +306,7 @@ else:
@_checks_drafts(
draft6="uri-reference",
draft7="uri-reference",
+ draft202012="uri-reference",
raises=ValueError,
)
def is_uri_reference(instance):
@@ -306,7 +330,10 @@ if validate_rfc3339:
return True
return validate_rfc3339(instance.upper())
- @_checks_drafts(draft7="time")
+ @_checks_drafts(
+ draft7="time",
+ draft202012="time",
+ )
def is_time(instance):
if not isinstance(instance, str):
return True
@@ -327,7 +354,12 @@ else:
return datetime.datetime.strptime(instance, "%Y-%m-%d")
-@_checks_drafts(draft3="date", draft7="date", raises=ValueError)
+@_checks_drafts(
+ draft3="date",
+ draft7="date",
+ draft202012="date",
+ raises=ValueError,
+)
def is_date(instance):
if not isinstance(instance, str):
return True
@@ -377,6 +409,7 @@ else:
@_checks_drafts(
draft6="json-pointer",
draft7="json-pointer",
+ draft202012="json-pointer",
raises=jsonpointer.JsonPointerException,
)
def is_json_pointer(instance):
@@ -390,6 +423,7 @@ else:
# into a new external library.
@_checks_drafts(
draft7="relative-json-pointer",
+ draft202012="relative-json-pointer",
raises=jsonpointer.JsonPointerException,
)
def is_relative_json_pointer(instance):
@@ -400,6 +434,10 @@ else:
non_negative_integer, rest = [], ""
for i, character in enumerate(instance):
if character.isdigit():
+ # digits with a leading "0" are not allowed
+ if i > 0 and int(instance[i-1]) == 0:
+ return False
+
non_negative_integer.append(character)
continue
@@ -419,8 +457,36 @@ else:
@_checks_drafts(
draft6="uri-template",
draft7="uri-template",
+ draft202012="uri-template",
)
def is_uri_template(instance):
if not isinstance(instance, str):
return True
return uri_template.validate(instance)
+
+
+try:
+ import isoduration
+except ImportError: # pragma: no cover
+ pass
+else:
+ @_checks_drafts(
+ draft202012="duration",
+ raises=isoduration.DurationParsingException,
+ )
+ def is_duration(instance):
+ if not isinstance(instance, str):
+ return True
+ return isoduration.parse_duration(instance)
+
+
+@_checks_drafts(
+ draft202012="uuid",
+ raises=ValueError,
+)
+def is_uuid(instance):
+ if not isinstance(instance, str):
+ return True
+ if "-" not in instance:
+ raise ValueError("Invalid UUID format")
+ return UUID(instance)