示例#1
0
def gather(
    *, schema: types.Schema, logical_name: str, schemas: types.Schemas
) -> types.ObjectArtifacts:
    """
    Collect artifacts from a specification for constructing an object reference.

    Get the prepared specification, reference logical name, back reference and foreign
    key column name from a raw object specification.

    Raise MalformedRelationshipError if neither $ref nor $allOf is found.
    Raise MalformedRelationshipError if uselist is defined but backref is not.
    Raise MalformedRelationshipError if multiple $ref, x-backref, x-secondary,
    x-foreign-key-column or x-uselist are found.

    Args:
        schema: The schema for the column.
        schemas: Used to resolve any $ref.
        logical_name: The logical name in the specification for the schema.

    Returns:
        The prepared specification, reference logical name, back reference and foreign
        key column.

    """
    intermediary_obj_artifacts = _handle_schema(
        logical_name=logical_name, schema=schema, schemas=schemas
    )

    # Check if uselist is defined and backref is not
    if (
        intermediary_obj_artifacts.uselist is not None
        and intermediary_obj_artifacts.backref is None
    ):
        raise exceptions.MalformedRelationshipError(
            "Relationships with x-uselist defined must also define x-backref."
        )

    # Construct back reference
    back_reference = None
    if intermediary_obj_artifacts.backref is not None:
        back_reference = types.BackReferenceArtifacts(
            property_name=intermediary_obj_artifacts.backref,
            uselist=intermediary_obj_artifacts.uselist,
        )

    return types.ObjectArtifacts(
        spec=intermediary_obj_artifacts.ref_schema,
        fk_column=intermediary_obj_artifacts.fk_column_name,
        relationship=types.RelationshipArtifacts(
            model_name=intermediary_obj_artifacts.ref_model_name,
            back_reference=back_reference,
            secondary=intermediary_obj_artifacts.secondary,
            kwargs=intermediary_obj_artifacts.kwargs,
        ),
        nullable=intermediary_obj_artifacts.nullable,
        description=intermediary_obj_artifacts.description,
    )
示例#2
0
def test_secondary(mocked_facades_models):
    """
    GIVEN schema with array referencing another schema and secondary set and schemas
    WHEN construct is called
    THEN table is set on models.
    """
    ref_schema = {
        "type": "object",
        "x-tablename": "ref_schema",
        "properties": {
            "id": {
                "type": "integer",
                "x-primary-key": True
            }
        },
    }
    secondary = "association"
    artifacts = types.ObjectArtifacts(
        spec=copy.deepcopy(ref_schema),
        fk_column="id",
        relationship=types.RelationshipArtifacts(model_name="RefSchema",
                                                 secondary=secondary),
    )
    tablename = "schema"
    model_schema = {
        "type": "object",
        "x-tablename": tablename,
        "properties": {
            "id": {
                "type": "integer",
                "x-primary-key": True
            }
        },
    }
    schemas = {"RefSchema": copy.deepcopy(ref_schema)}

    array_ref._link.construct(artifacts=artifacts,
                              model_schema=model_schema,
                              schemas=schemas)

    assert mocked_facades_models.set_association.call_count == 1
    if sys.version_info[1] == 8:
        name = mocked_facades_models.set_association.call_args.kwargs["name"]
        table = mocked_facades_models.set_association.call_args.kwargs["table"]
    else:
        _, kwargs = mocked_facades_models.set_association.call_args
        name = kwargs["name"]
        table = kwargs["table"]
    assert name == secondary
    assert table.name == secondary
    assert schemas == {"RefSchema": ref_schema}
示例#3
0
def test_schemas():
    """
    GIVEN schema with array referencing another schema and schemas
    WHEN construct is called
    THEN foreign key is added to the referenced schema.
    """
    ref_schema = {
        "type": "object",
        "x-tablename": "ref_schema",
        "properties": {}
    }
    artifacts = types.ObjectArtifacts(
        spec=copy.deepcopy(ref_schema),
        fk_column="id",
        relationship=types.RelationshipArtifacts(model_name="RefSchema"),
    )
    tablename = "schema"
    model_schema = {
        "type": "object",
        "x-tablename": tablename,
        "properties": {
            "id": {
                "type": "integer"
            }
        },
    }
    schemas = {"RefSchema": copy.deepcopy(ref_schema)}

    array_ref._link.construct(artifacts=artifacts,
                              model_schema=model_schema,
                              schemas=schemas)

    assert schemas == {
        "RefSchema": {
            "allOf": [
                ref_schema,
                {
                    "type": "object",
                    "properties": {
                        f"{tablename}_id": {
                            "type": "integer",
                            "x-foreign-key": f"{tablename}.id",
                            "x-dict-ignore": True,
                        }
                    },
                },
            ]
        }
    }
示例#4
0
    def test_invalid():
        """
        GIVEN artifacts with None BackReferenceArtifacts
        WHEN _calculate_schema is called with the artifacts
        THEN MissingArgumentError is raised.
        """
        artifacts = types.ObjectArtifacts(
            spec={},
            fk_column="fk_column",
            relationship=types.RelationshipArtifacts(
                model_name="RefModel", back_reference=None, secondary=None
            ),
        )

        with pytest.raises(exceptions.MissingArgumentError):
            backref._calculate_schema(
                artifacts=artifacts, ref_from_array=False, model_name="Model"
            )
示例#5
0
def test_record():
    """
    GIVEN artifacts, schemas, whether the reference is from an array and the model name
    WHEN record is called with the arguments
    THEN the back reference schema is recorded on the references model.
    """
    artifacts = types.ObjectArtifacts(
        spec={},
        logical_name="logical name 1",
        fk_column="fk_column",
        relationship=types.RelationshipArtifacts(
            model_name="RefModel",
            back_reference=types.BackReferenceArtifacts(property_name="model"),
        ),
    )
    schemas = {"RefModel": {"type": "object", "properties": {}}}

    backref.record(artifacts=artifacts,
                   ref_from_array=False,
                   model_name="Model",
                   schemas=schemas)

    assert schemas == {
        "RefModel": {
            "allOf": [
                {
                    "type": "object",
                    "properties": {}
                },
                {
                    "type": "object",
                    "x-backrefs": {
                        "model": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "x-de-$ref": "Model"
                            },
                        }
                    },
                },
            ]
        }
    }
示例#6
0
def test_record_backref_none():
    """
    GIVEN artifacts with None backref
    WHEN record is called with the artifacts
    THEN MissingArgumentError is raised.
    """
    artifacts = types.ObjectArtifacts(
        spec={},
        fk_column="fk_column",
        relationship=types.RelationshipArtifacts(
            model_name="RefModel", back_reference=None, secondary=None
        ),
    )
    schemas = {"RefModel": {"type": "object", "properties": {}}}

    backref.record(
        artifacts=artifacts, ref_from_array=False, model_name="Model", schemas={}
    )

    assert schemas == {"RefModel": {"type": "object", "properties": {}}}
示例#7
0
    def test_valid(ref_from_array, uselist, secondary, expected_schema):
        """
        GIVEN whether referenced from array, uselist, secondary, model name
        WHEN _calculate_schema is called with the parameters
        THEN the given expected schema is returned.
        """
        artifacts = types.ObjectArtifacts(
            spec={},
            fk_column="fk_column",
            relationship=types.RelationshipArtifacts(
                model_name="RefModel",
                back_reference=types.BackReferenceArtifacts(
                    property_name="model", uselist=uselist
                ),
                secondary=secondary,
            ),
        )

        returned_schema = backref._calculate_schema(
            artifacts=artifacts, ref_from_array=ref_from_array, model_name="Model"
        )

        assert returned_schema == expected_schema
示例#8
0
"""Tests for _calculate_schema."""
# pylint: disable=protected-access

import pytest

from open_alchemy import types
from open_alchemy.column_factory import object_ref


@pytest.mark.parametrize(
    "artifacts, expected_schema",
    [
        (
            types.ObjectArtifacts(
                spec={},
                fk_column="fk_column",
                relationship=types.RelationshipArtifacts("RefSchema"),
            ),
            {
                "type": "object",
                "x-de-$ref": "RefSchema"
            },
        ),
        (
            types.ObjectArtifacts(
                spec={},
                fk_column="fk_column",
                relationship=types.RelationshipArtifacts("RefSchema"),
                nullable=True,
            ),
            {
示例#9
0
"""Tests for schema."""
# pylint: disable=protected-access

import pytest

from open_alchemy import types
from open_alchemy.column_factory import array_ref


@pytest.mark.parametrize(
    "artifacts, expected_schema",
    [
        pytest.param(
            types.ObjectArtifacts(
                spec={},
                logical_name="logical name 1",
                fk_column="fk_column",
                relationship=types.RelationshipArtifacts("RefSchema"),
            ),
            {"type": "array", "items": {"type": "object", "x-de-$ref": "RefSchema"}},
            id="plain",
        ),
        pytest.param(
            types.ObjectArtifacts(
                spec={},
                logical_name="logical name 1",
                fk_column="fk_column",
                relationship=types.RelationshipArtifacts("RefSchema"),
                description="description 1",
            ),
            {
                "type": "array",