Skip to content

Commit

Permalink
Merge branch 'master' into mai/aihttp-exception-handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov committed Dec 1, 2024
2 parents 3e4ddd9 + 42476f3 commit c275789
Show file tree
Hide file tree
Showing 51 changed files with 1,637 additions and 606 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
from pathlib import Path

import jsonref
from common_library.json_serialization import json_dumps
from models_library.services import ServiceMetaDataPublished

CURRENT_DIR = Path(sys.argv[0] if __name__ == "__main__" else __file__).resolve().parent


if __name__ == "__main__":
with Path.open(CURRENT_DIR.parent / "node-meta-v0.0.1-pydantic.json", "w") as f:
schema = ServiceMetaDataPublished.schema_json()
schema = json_dumps(ServiceMetaDataPublished.model_json_schema())
schema_without_ref = jsonref.loads(schema)

json.dump(schema_without_ref, f, indent=2)
3 changes: 2 additions & 1 deletion api/specs/director/schemas/scripts/create_project-schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pathlib import Path

import jsonref
from common_library.json_serialization import json_dumps
from models_library.projects import Project

CURRENT_DIR = Path(sys.argv[0] if __name__ == "__main__" else __file__).resolve().parent
Expand All @@ -17,7 +18,7 @@
with Path.open(
CURRENT_DIR.parent / "common/schemas/project-v0.0.1-pydantic.json", "w"
) as f:
schema = Project.schema_json()
schema = json_dumps(Project.model_json_schema())
schema_without_ref = jsonref.loads(schema)

json.dump(schema_without_ref, f, indent=2)
7 changes: 0 additions & 7 deletions packages/models-library/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@ tests-ci: ## runs unit tests [ci-mode]
-m "not heavy_load" \
$(CURDIR)/tests

.PHONY: project-jsonschema.ignore.json
project-jsonschema.ignore.json: ## creates project-v0.0.1.json for DEV purposes
python3 -c "from models_library.projects import Project; print(Project.schema_json(indent=2))" > $@

.PHONY: service-jsonschema.ignore.json
node-meta-jsonschema.ignore.json: ## creates node-meta-v0.0.1.json for DEV purposes
python3 -c "from models_library.services import ServiceDockerData as cls; print(cls.schema_json(indent=2))" > $@

DOCKER_API_VERSION ?= 1.41
.PHONY: docker_rest_api.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@
from copy import deepcopy
from typing import Any

from pydantic import schema_of
from pydantic import TypeAdapter

from ...projects_nodes import OutputID, OutputsDict
from ...services import ServiceMetaDataPublished, ServiceType
from ...services_constants import LATEST_INTEGRATION_VERSION
from .._key_labels import FUNCTION_SERVICE_KEY_PREFIX
from .._utils import EN, OM, FunctionServices, create_fake_thumbnail_url

LIST_NUMBERS_SCHEMA: dict[str, Any] = schema_of(list[float], title="list[number]")
LIST_NUMBERS_SCHEMA: dict[str, Any] = {
**TypeAdapter(list[float]).json_schema(),
"title": "list[number]",
}


META = ServiceMetaDataPublished.model_validate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class MyModel(BaseModel):

from common_library.json_serialization import json_loads
from orjson import JSONDecodeError
from pydantic import BaseModel


def empty_str_to_none_pre_validator(value: Any):
Expand Down Expand Up @@ -102,8 +103,8 @@ def create__check_only_one_is_set__root_validator(alternative_field_names: list[
SEE test_uid_or_email_are_set.py for more details
"""

def _validator(cls, values):
assert set(alternative_field_names).issubset(cls.__fields__) # nosec
def _validator(cls: type[BaseModel], values):
assert set(alternative_field_names).issubset(cls.model_fields) # nosec

got = {
field_name: getattr(values, field_name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
from copy import deepcopy
from typing import Any, Literal

from pydantic import schema_of
from pydantic import TypeAdapter

from ..services import ServiceInput, ServiceOutput
from ..services_regex import PROPERTY_TYPE_TO_PYTHON_TYPE_MAP

PortKindStr = Literal["input", "output"]
JsonSchemaDict = dict[str, Any]


_PROPERTY_TYPE_TO_SCHEMAS = {
property_type: schema_of(python_type, title=property_type.capitalize())
property_type: {
**TypeAdapter(python_type).json_schema(),
"title": property_type.capitalize(),
}
for property_type, python_type in PROPERTY_TYPE_TO_PYTHON_TYPE_MAP.items()
}

Expand Down
3 changes: 1 addition & 2 deletions packages/models-library/tests/test__models_fit_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# pylint:disable=unused-argument
# pylint:disable=redefined-outer-name
# pylint:disable=protected-access
import json
from collections.abc import Callable

import pytest
Expand All @@ -28,7 +27,7 @@ def test_generated_schema_same_as_original(
# TODO: create instead a fixture that returns a Callable and do these checks
# on separate test_* files that follow the same package submodule's hierarchy
#
generated_schema = json.loads(pydantic_model.schema_json(indent=2))
generated_schema = pydantic_model.model_json_schema()
original_schema = json_schema_dict(original_json_schema)

# NOTE: A change is considered an addition when the destination schema has become more permissive relative to the source schema. For example {"type": "string"} -> {"type": ["string", "number"]}.
Expand Down
7 changes: 5 additions & 2 deletions packages/models-library/tests/test__pydantic_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
from typing import Any, Union, get_args, get_origin

import pytest
from common_library.json_serialization import json_dumps
from models_library.projects_nodes import InputTypes, OutputTypes
from models_library.projects_nodes_io import SimCoreFileLink
from pydantic import BaseModel, Field, ValidationError, schema_json_of
from pydantic import BaseModel, Field, TypeAdapter, ValidationError
from pydantic.types import Json
from pydantic.version import version_short

Expand All @@ -37,7 +38,9 @@ class ArgumentAnnotation(BaseModel):
data_schema: Json

# notice that this is a raw string!
jsonschema_of_x = schema_json_of(list[int], title="schema[x]")
jsonschema_of_x = json_dumps(
{**TypeAdapter(list[int]).json_schema(), "title": "schema[x]"}
)
assert isinstance(jsonschema_of_x, str)

x_annotation = ArgumentAnnotation(name="x", data_schema=jsonschema_of_x)
Expand Down
4 changes: 2 additions & 2 deletions packages/models-library/tests/test_service_settings_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pprint import pformat
from typing import Any, Final, NamedTuple

import pydantic_core
import pytest
from models_library.basic_types import PortInt
from models_library.osparc_variable_identifier import (
Expand All @@ -32,7 +33,6 @@
from models_library.services_resources import DEFAULT_SINGLE_SERVICE_NAME
from models_library.utils.string_substitution import TextTemplate
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic.json import pydantic_encoder


class _Parametrization(NamedTuple):
Expand Down Expand Up @@ -560,7 +560,7 @@ def test_can_parse_labels_with_osparc_identifiers(

def servicelib__json_serialization__json_dumps(obj: Any, **kwargs):
# Analogous to 'models_library.utils.json_serialization.json_dumps'
return json.dumps(obj, default=pydantic_encoder, **kwargs)
return json.dumps(obj, default=pydantic_core.to_jsonable_python, **kwargs)


def test_resolving_some_service_labels_at_load_time(
Expand Down
3 changes: 2 additions & 1 deletion packages/models-library/tests/test_services_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path

import yaml
from common_library.json_serialization import json_dumps
from models_library.services import ServiceInput, ServiceMetaDataPublished
from pint import Unit, UnitRegistry

Expand All @@ -13,7 +14,7 @@ def test_service_port_units(tests_data_dir: Path):
ureg = UnitRegistry()

data = yaml.safe_load((tests_data_dir / "metadata-sleeper-2.0.2.yaml").read_text())
print(ServiceMetaDataPublished.schema_json(indent=2))
print(json_dumps(ServiceMetaDataPublished.model_json_schema(), indent=2))

service_meta = ServiceMetaDataPublished.model_validate(data)
assert service_meta.inputs
Expand Down
2 changes: 1 addition & 1 deletion packages/models-library/tests/test_sidecar_volumes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ def test_volume_state_equality_does_not_use_last_changed(status: VolumeStatus):
# NOTE: `last_changed` is initialized with the utc datetime
# at the moment of the creation of the object.
assert VolumeState(status=status) == VolumeState(status=status)
schema_property_count = len(VolumeState.schema()["properties"])
schema_property_count = len(VolumeState.model_json_schema()["properties"])
assert len(VolumeState(status=status).model_dump()) == schema_property_count
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def create_service_out2(**overrides):
# https://github.com/ITISFoundation/osparc-simcore/blob/master/services/catalog/src/simcore_service_catalog/models/schemas/services.py
#
# docker exec -it $(docker ps --filter="ancestor=local/catalog:development" -q)
# python -c "from simcore_service_catalog.models.schemas.services import ServiceOut;print(ServiceOut.schema_json(indent=2))" > services/catalog/ignore-schema.json
# put file in https://json-schema-faker.js.org/ and get fake output
#

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import pytest
from models_library.services import ServiceInput
from pydantic import Field, ValidationError, schema_of
from pydantic import Field, TypeAdapter, ValidationError
from simcore_sdk.node_ports_v2 import exceptions
from simcore_sdk.node_ports_v2.port import Port
from simcore_sdk.node_ports_v2.ports_mapping import InputsList, OutputsList
Expand Down Expand Up @@ -74,10 +74,11 @@ def test_io_ports_are_not_aliases():
@pytest.fixture
def fake_port_meta() -> dict[str, Any]:
"""Service port metadata: defines a list of non-negative numbers"""
schema = schema_of(
list[Annotated[float, Field(ge=0)]],
title="list[non-negative number]",
)
schema = {
**TypeAdapter(list[Annotated[float, Field(ge=0)]]).json_schema(),
"title": "list[non-negative number]",
}

schema.update(
description="Port with an array of numbers",
x_unit="millimeter",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
from unittest.mock import AsyncMock

import pytest
from pydantic import BaseModel, Field, schema_of
from pydantic import ValidationError
from pydantic import BaseModel, Field, TypeAdapter, ValidationError
from simcore_sdk.node_ports_v2.port import Port
from simcore_sdk.node_ports_v2.port_validation import (
PortUnitError,
Expand Down Expand Up @@ -132,17 +131,22 @@ class A(BaseModel):
i: Annotated[int, Field(gt=3)]
b: bool = False
s: str
l: list[int]
t: list[int]

content_schema = _resolve_refs(schema_of(list[A], title="array[A]"))
content_schema = _resolve_refs(
{
**TypeAdapter(list[A]).json_schema(),
"title": "array[A]",
}
)

port_meta = {
"label": "array_",
"description": "Some array of As",
"type": "ref_contentSchema",
"contentSchema": content_schema,
}
sample = [{"i": 5, "s": "x", "l": [1, 2]}, {"i": 6, "s": "y", "l": [2]}]
sample = [{"i": 5, "s": "x", "t": [1, 2]}, {"i": 6, "s": "y", "t": [2]}]
expected_value = [A(**i).model_dump() for i in sample]

print(json.dumps(port_meta, indent=1))
Expand Down
Loading

0 comments on commit c275789

Please sign in to comment.