Skip to content
Merged
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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ vendor/lock: $(VENDOR_LOCK)
vendor/sync:
# regenerate vendor.txt file (exported from lockfile)
@pushd $(VENDOR_SRC) && $(POETRY_BIN) export --without-hashes 2> /dev/null \
| egrep -v "(importlib|zipp)" \
| grep -E -v "(importlib|zipp)" \
| sort > $(VENDOR_TXT)

# vendor packages
@vendoring sync
@$(POETRY_BIN) run vendoring sync

# strip out *.pyi stubs
@find "$(VENDOR_DIR)" -type f -name "*.pyi" -exec rm {} \;
Expand Down
35 changes: 24 additions & 11 deletions src/poetry/core/_vendor/jsonschema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,13 @@
The main functionality is provided by the validator classes for each of the
supported JSON Schema versions.

Most commonly, `validate` is the quickest way to simply validate a given
instance under a schema, and will create a validator for you.
Most commonly, `jsonschema.validators.validate` is the quickest way to simply
validate a given instance under a schema, and will create a validator
for you.
"""
import warnings

from jsonschema._format import (
FormatChecker,
draft3_format_checker,
draft4_format_checker,
draft6_format_checker,
draft7_format_checker,
draft201909_format_checker,
draft202012_format_checker,
)
from jsonschema._format import FormatChecker
from jsonschema._types import TypeChecker
from jsonschema.exceptions import (
ErrorTree,
Expand Down Expand Up @@ -55,4 +48,24 @@ def __getattr__(name):
import importlib_metadata as metadata

return metadata.version("jsonschema")

format_checkers = {
"draft3_format_checker": Draft3Validator,
"draft4_format_checker": Draft4Validator,
"draft6_format_checker": Draft6Validator,
"draft7_format_checker": Draft7Validator,
"draft201909_format_checker": Draft201909Validator,
"draft202012_format_checker": Draft202012Validator,
}
ValidatorForFormat = format_checkers.get(name)
if ValidatorForFormat is not None:
warnings.warn(
f"Accessing jsonschema.{name} is deprecated and will be "
"removed in a future release. Instead, use the FORMAT_CHECKER "
"attribute on the corresponding Validator.",
DeprecationWarning,
stacklevel=2,
)
return ValidatorForFormat.FORMAT_CHECKER

raise AttributeError(f"module {__name__} has no attribute {name}")
47 changes: 31 additions & 16 deletions src/poetry/core/_vendor/jsonschema/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ipaddress
import re
import typing
import warnings

from jsonschema.exceptions import FormatError

Expand All @@ -16,7 +17,7 @@
]


class FormatChecker(object):
class FormatChecker:
"""
A ``format`` property checker.

Expand All @@ -27,13 +28,12 @@ class FormatChecker(object):
`FormatChecker` objects always return ``True`` when asked about
formats that they do not know how to validate.

To check a custom format using a function that takes an instance and
returns a ``bool``, use the `FormatChecker.checks` or
`FormatChecker.cls_checks` decorators.
To add a check for a custom format use the `FormatChecker.checks`
decorator.

Arguments:

formats (~collections.abc.Iterable):
formats:

The known formats to validate. This argument can be used to
limit which formats will be used during validation.
Expand All @@ -44,11 +44,10 @@ class FormatChecker(object):
tuple[_FormatCheckCallable, _RaisesType],
] = {}

def __init__(self, formats: typing.Iterable[str] | None = None):
def __init__(self, formats: typing.Iterable[str] = None):
if formats is None:
self.checkers = self.checkers.copy()
else:
self.checkers = dict((k, self.checkers[k]) for k in formats)
formats = self.checkers.keys()
self.checkers = {k: self.checkers[k] for k in formats}

def __repr__(self):
return "<FormatChecker checkers={}>".format(sorted(self.checkers))
Expand All @@ -61,11 +60,11 @@ def checks(

Arguments:

format (str):
format:

The format that the decorated function will check.

raises (Exception):
raises:

The exception(s) raised by the decorated function when an
invalid instance is found.
Expand All @@ -84,6 +83,21 @@ def _checks(func: _F) -> _F:
@classmethod
def cls_checks(
cls, format: str, raises: _RaisesType = (),
) -> typing.Callable[[_F], _F]:
warnings.warn(
(
"FormatChecker.cls_checks is deprecated. Call "
"FormatChecker.checks on a specific FormatChecker instance "
"instead."
),
DeprecationWarning,
stacklevel=2,
)
return cls._cls_checks(format=format, raises=raises)

@classmethod
def _cls_checks(
cls, format: str, raises: _RaisesType = (),
) -> typing.Callable[[_F], _F]:
def _checks(func: _F) -> _F:
cls.checkers[format] = (func, raises)
Expand All @@ -101,14 +115,15 @@ def check(self, instance: object, format: str) -> None:

The instance to check

format (str):
format:

The format that instance should conform to


Raises:

FormatError: if the instance does not conform to ``format``
FormatError:

if the instance does not conform to ``format``
"""

if format not in self.checkers:
Expand All @@ -133,7 +148,7 @@ def conforms(self, instance: object, format: str) -> bool:

The instance to check

format (str):
format:

The format that instance should conform to

Expand Down Expand Up @@ -204,7 +219,7 @@ def wrap(func: _F) -> _F:

# Oy. This is bad global state, but relied upon for now, until
# deprecation. See #519 and test_format_checkers_come_with_defaults
FormatChecker.cls_checks(
FormatChecker._cls_checks(
draft202012 or draft201909 or draft7 or draft6 or draft4 or draft3,
raises,
)(func)
Expand Down
91 changes: 91 additions & 0 deletions src/poetry/core/_vendor/jsonschema/_legacy_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
from jsonschema.exceptions import ValidationError


def id_of_ignore_ref(property="$id"):
def id_of(schema):
"""
Ignore an ``$id`` sibling of ``$ref`` if it is present.

Otherwise, return the ID of the given schema.
"""
if schema is True or schema is False or "$ref" in schema:
return ""
return schema.get(property, "")
return id_of


def ignore_ref_siblings(schema):
"""
Ignore siblings of ``$ref`` if it is present.
Expand Down Expand Up @@ -226,3 +239,81 @@ def recursiveRef(validator, recursiveRef, instance, schema):
# see it.
subschema
return []


def find_evaluated_item_indexes_by_schema(validator, instance, schema):
"""
Get all indexes of items that get evaluated under the current schema

Covers all keywords related to unevaluatedItems: items, prefixItems, if,
then, else, contains, unevaluatedItems, allOf, oneOf, anyOf
"""
if validator.is_type(schema, "boolean"):
return []
evaluated_indexes = []

if "additionalItems" in schema:
return list(range(0, len(instance)))

if "$ref" in schema:
scope, resolved = validator.resolver.resolve(schema["$ref"])
validator.resolver.push_scope(scope)

try:
evaluated_indexes += find_evaluated_item_indexes_by_schema(
validator, instance, resolved,
)
finally:
validator.resolver.pop_scope()

if "items" in schema:
if validator.is_type(schema["items"], "object"):
return list(range(0, len(instance)))
evaluated_indexes += list(range(0, len(schema["items"])))

if "if" in schema:
if validator.evolve(schema=schema["if"]).is_valid(instance):
evaluated_indexes += find_evaluated_item_indexes_by_schema(
validator, instance, schema["if"],
)
if "then" in schema:
evaluated_indexes += find_evaluated_item_indexes_by_schema(
validator, instance, schema["then"],
)
else:
if "else" in schema:
evaluated_indexes += find_evaluated_item_indexes_by_schema(
validator, instance, schema["else"],
)

for keyword in ["contains", "unevaluatedItems"]:
if keyword in schema:
for k, v in enumerate(instance):
if validator.evolve(schema=schema[keyword]).is_valid(v):
evaluated_indexes.append(k)

for keyword in ["allOf", "oneOf", "anyOf"]:
if keyword in schema:
for subschema in schema[keyword]:
errs = list(validator.descend(instance, subschema))
if not errs:
evaluated_indexes += find_evaluated_item_indexes_by_schema(
validator, instance, subschema,
)

return evaluated_indexes


def unevaluatedItems_draft2019(validator, unevaluatedItems, instance, schema):
if not validator.is_type(instance, "array"):
return
evaluated_item_indexes = find_evaluated_item_indexes_by_schema(
validator, instance, schema,
)
unevaluated_items = [
item for index, item in enumerate(instance)
if index not in evaluated_item_indexes
]
if unevaluated_items:
error = "Unevaluated items are not allowed (%s %s unexpected)"
yield ValidationError(error % _utils.extras_msg(unevaluated_items))
Loading