Ejemplo n.º 1
0
def check_schema_schemas_dict(schema: types.Schema, schemas: types.Schemas) -> None:
    """Check that schema and schemas are dict."""
    # Check schema and schemas are dict
    if not isinstance(schema, dict):
        raise exceptions.MalformedSchemaError("The schema must be a dictionary.")
    if not isinstance(schemas, dict):
        raise exceptions.MalformedSchemaError("The schemas must be a dictionary.")
Ejemplo n.º 2
0
def _handle_object_reference(*, spec: types.Schema,
                             schemas: types.Schemas) -> types.Schema:
    """
    Determine the foreign key schema for an object reference.

    Args:
        spec: The schema of the object reference.
        schemas: All defined schemas.

    Returns:
        The foreign key schema.

    """
    tablename = helpers.get_ext_prop(source=spec, name="x-tablename")
    if not tablename:
        raise exceptions.MalformedSchemaError(
            "Referenced object is missing x-tablename property.")
    properties = spec.get("properties")
    if properties is None:
        raise exceptions.MalformedSchemaError(
            "Referenced object does not have any properties.")
    logical_name = "id"
    id_spec = properties.get(logical_name)
    if id_spec is None:
        raise exceptions.MalformedSchemaError(
            "Referenced object does not have id property.")
    # Preparing specification
    prepared_id_spec = helpers.prepare_schema(schema=id_spec, schemas=schemas)
    id_type = prepared_id_spec.get("type")
    if id_type is None:
        raise exceptions.MalformedSchemaError(
            "Referenced object id property does not have a type.")

    return {"type": id_type, "x-foreign-key": f"{tablename}.id"}
Ejemplo n.º 3
0
def _resolve(
    name: str,
    schema: types.Schema,
    schemas: types.Schemas,
    seen_refs: typing.Set[str],
    skip_name: typing.Optional[str],
) -> NameSchema:
    """Implement resolve."""
    # Checking whether schema is a reference schema
    ref = schema.get(types.OpenApiProperties.REF)
    if ref is None:
        return name, schema
    # Check that ref is string
    if not isinstance(ref, str):
        raise exceptions.MalformedSchemaError(
            "The value of $ref must be a string.")

    # Check for circular $ref
    if ref in seen_refs:
        raise exceptions.MalformedSchemaError(
            "Circular reference chain detected.")
    seen_refs.add(ref)

    ref_name, ref_schema = get_ref(ref=ref, schemas=schemas)

    # Check if schema should be skipped
    if ref_name == skip_name:
        return name, {}

    return _resolve(ref_name, ref_schema, schemas, seen_refs, skip_name)
Ejemplo n.º 4
0
def convert(*, value: types.TColumnDefault, type_: str,
            format_: typing.Optional[str]) -> types.TPyColumnDefault:
    """
    Convert an OpenAPI value to it's python type based on the format.

    Args:
        value: The value to convert.
        type_: The OpenAPI type.
        format_: The OpenAPI format.

    Returns:
        The value converted to its equivalent Python type.

    """
    if type_ in {"object", "array"}:
        raise exceptions.MalformedSchemaError(
            "Cannot convert object nor array types to Python equivalent values."
        )

    if isinstance(value, str) and format_ == "date":
        try:
            return datetime.date.fromisoformat(value)
        except ValueError:
            raise exceptions.MalformedSchemaError("Invalid date string.")
    if isinstance(value, str) and format_ == "date-time":
        try:
            return datetime.datetime.fromisoformat(value)
        except ValueError:
            raise exceptions.MalformedSchemaError("Invalid date-time string.")
    if isinstance(value, str) and format_ == "binary":
        return value.encode()
    if format_ == "double":
        raise exceptions.MalformedSchemaError(
            "Double format is not supported.")
    return value
Ejemplo n.º 5
0
def _prepare_schema_object_common(
    *, schema: types.Schema, schemas: types.Schemas, array_context: bool
) -> types.ReadOnlySchemaObjectCommon:
    """
    Check and transform readOnly schema to consistent format.

    Args:
        schema: The readOnly schema to operate on.
        schemas: Used to resolve any $ref.
        array_context: Whether checking is being done at the array items level. Changes
            exception messages and schema validation.

    Returns:
        The schema in a consistent format.

    """
    # Check type
    try:
        type_ = helpers.peek.type_(schema=schema, schemas=schemas)
    except exceptions.TypeMissingError:
        raise exceptions.MalformedSchemaError(
            "Every readOnly property must have a type."
            if not array_context
            else "Array readOnly items must have a type."
        )

    schema = helpers.prepare_schema(schema=schema, schemas=schemas)

    if type_ != "object":
        raise exceptions.MalformedSchemaError(
            "readOnly array item type must be an object."
            if array_context
            else "readyOnly property must be of type array or object."
        )

    # Handle object
    properties = schema.get("properties")
    if properties is None:
        raise exceptions.MalformedSchemaError(
            "readOnly object definition must include properties."
        )
    if not properties:
        raise exceptions.MalformedSchemaError(
            "readOnly object definition must include at least 1 property."
        )

    # Initialize schema properties to return
    properties_schema: types.Schema = {}

    # Process properties
    for property_name, property_schema in properties.items():
        property_type = helpers.peek.type_(schema=property_schema, schemas=schemas)
        if property_type in {"array", "object"}:
            raise exceptions.MalformedSchemaError(
                "readOnly object properties cannot be of type array nor object."
            )
        properties_schema[property_name] = {"type": property_type}

    return {"type": "object", "properties": properties_schema}
Ejemplo n.º 6
0
def _check_artifacts(*, artifacts: types.ColumnArtifacts) -> None:
    """
    Check that the artifacts comply with overall rules.

    Raise MalformedSchemaError for:
        1. maxLength with
            a. integer
            b. number
            c. boolean
            d. JSON
            e. string with the format of
                i. date
                ii. date-time
        2. autoincrement with
            a. number
            b. string
            c. boolean
            d. JSON
        3. format with
            a. boolean
        4. default with JSON

    Args:
        artifacts: The artifacts to check.

    """
    # Check whether max length was used incorrectly
    if artifacts.open_api.max_length is not None:
        if artifacts.open_api.type != "string":
            raise exceptions.MalformedSchemaError(
                f"maxLength is not supported for {artifacts.open_api.type}"
            )
        # Must be string type
        if artifacts.open_api.format in {"date", "date-time"}:
            raise exceptions.MalformedSchemaError(
                "maxLength is not supported for string with the format "
                f"{artifacts.open_api.format}"
            )
    # Check whether autoincrement was used incorrectly
    if artifacts.extension.autoincrement is not None:
        if artifacts.open_api.type != "integer":
            raise exceptions.MalformedSchemaError(
                f"autoincrement is not supported for {artifacts.open_api.type}"
            )
    # Check whether format was used with boolean
    if artifacts.open_api.type == "boolean" and artifacts.open_api.format is not None:
        raise exceptions.MalformedSchemaError("format is not supported for boolean")
    # Check whether default was used with JSON column
    if artifacts.extension.json and artifacts.open_api.default is not None:
        raise exceptions.FeatureNotImplementedError(
            "default is not supported for JSON column"
        )
Ejemplo n.º 7
0
def _check_kwargs(*, value: typing.Any,
                  key: str) -> typing.Dict[str, typing.Any]:
    """Check the kwargs value."""
    # Check value
    if not isinstance(value, dict):
        raise exceptions.MalformedSchemaError(
            f"The {key} property must be of type dict.")
    # Check keys
    not_str_keys = filter(lambda key: not isinstance(key, str), value.keys())
    if next(not_str_keys, None) is not None:
        raise exceptions.MalformedSchemaError(
            f"The {key} property must have string keys.")
    return value
Ejemplo n.º 8
0
def _resolve(
    name: str,
    schema: types.Schema,
    schemas: types.Schemas,
    seen_refs: typing.Set[str],
    skip_name: typing.Optional[str],
) -> NameSchema:
    """Implement resolve."""
    # Checking whether schema is a reference schema
    ref = schema.get("$ref")
    if ref is None:
        return name, schema

    # Check for circular $ref
    if ref in seen_refs:
        raise exceptions.MalformedSchemaError(
            "Circular reference chain detected.")
    seen_refs.add(ref)

    ref_name, ref_schema = get_ref(ref=ref, schemas=schemas)

    # Check if schema should be skipped
    if ref_name == skip_name:
        return name, {}

    return _resolve(ref_name, ref_schema, schemas, seen_refs, skip_name)
Ejemplo n.º 9
0
def default(*, schema: types.Schema, schemas: types.Schemas) -> types.TColumnDefault:
    """
    Retrieve the default value and check it against the schema.

    Args:
        schema: The schema to retrieve the default value from.

    """
    # Retrieve value
    value = peek_key(schema=schema, schemas=schemas, key="default")
    if value is None:
        return None
    # Assemble schema
    resolved_schema: types.ColumnSchema = {
        "type": type_(schema=schema, schemas=schemas)
    }
    format_value = format_(schema=schema, schemas=schemas)
    max_length_value = max_length(schema=schema, schemas=schemas)
    if format_value is not None:
        resolved_schema["format"] = format_value
    if max_length_value is not None:
        resolved_schema["maxLength"] = max_length_value
    try:
        facades.jsonschema.validate(value, resolved_schema)
    except facades.jsonschema.ValidationError:
        raise exceptions.MalformedSchemaError(
            f"The default value does not conform to the schema. The value is: {value}"
        )
    return value
Ejemplo n.º 10
0
def _peek_key(schema: types.Schema, schemas: types.Schemas, key: str,
              seen_refs: typing.Set[str]) -> typing.Any:
    """Implement peek_key."""
    # Base case, look for type key
    value = schema.get(key)
    if value is not None:
        return value

    # Recursive case, look for $ref
    ref_value = schema.get("$ref")
    if ref_value is not None:
        # Check for circular $ref
        if ref_value in seen_refs:
            raise exceptions.MalformedSchemaError(
                "Circular reference detected.")
        seen_refs.add(ref_value)

        _, ref_schema = ref.get_ref(ref=ref_value, schemas=schemas)
        return _peek_key(ref_schema, schemas, key, seen_refs)

    # Recursive case, look for allOf
    all_of = schema.get("allOf")
    if all_of is not None:
        for sub_schema in all_of:
            value = _peek_key(sub_schema, schemas, key, seen_refs)
            if value is not None:
                return value

    # Base case, type or ref not found or no type in allOf
    return None
Ejemplo n.º 11
0
def inherits(
        *, schema: types.Schema,
        schemas: types.Schemas) -> typing.Optional[typing.Union[str, bool]]:
    """
    Retrieve the value of the x-inherits extension property of the schema.

    Raises MalformedSchemaError if the value is not a string nor a boolean.

    Args:
        schema: The schema to get x-inherits from.
        schemas: The schemas for $ref lookup.

    Returns:
        The inherits or None.

    """
    value = peek_key(schema=schema,
                     schemas=schemas,
                     key=types.ExtensionProperties.INHERITS)
    if value is None:
        return None
    if not isinstance(value, (str, bool)):
        raise exceptions.MalformedSchemaError(
            "The x-inherits property must be of type string or boolean.")
    return value
Ejemplo n.º 12
0
def nullable(*, schema: types.Schema,
             schemas: types.Schemas) -> typing.Optional[bool]:
    """
    Retrieve the nullable property from a property schema or null from the type array.

    Raises MalformedSchemaError if the nullable value is not a boolean.

    Args:
        schema: The schema to get the nullable from.
        schemas: The schemas for $ref lookup.

    Returns:
        The nullable value or whether 'null' is in the type array.

    """
    nullable_value = peek_key(schema=schema,
                              schemas=schemas,
                              key=types.OpenApiProperties.NULLABLE)
    if nullable_value is not None and not isinstance(nullable_value, bool):
        raise exceptions.MalformedSchemaError(
            "A nullable value must be of type boolean.")

    type_value = peek_key(schema=schema,
                          schemas=schemas,
                          key=types.OpenApiProperties.TYPE)

    if nullable_value is None and not isinstance(type_value, list):
        return None

    return nullable_value is True or (isinstance(type_value, list)
                                      and "null" in type_value)
Ejemplo n.º 13
0
def check_sub_schema_dict(sub_schema: typing.Any) -> dict:
    """Check that a sub schema in an allOf is a dict."""
    if not isinstance(sub_schema, dict):
        raise exceptions.MalformedSchemaError(
            "The elements of allOf must be dictionaries."
        )
    return sub_schema
Ejemplo n.º 14
0
def _check_artifacts(*, artifacts: types.ColumnArtifacts) -> None:
    """
    Check that the artifacts comply with overall rules.

    Raise MalformedSchemaError for:
        1. maxLength with
            a. integer
            b. number
            c. boolean
            d. string with the format of
                i. date
                ii. date-time
        2. autoincrement with
            a. number
            b. string
            c. boolean
        3. format with
            a. boolean

    Args:
        artifacts: The artifacts to check.

    """
    if artifacts.open_api.max_length is not None:
        if artifacts.open_api.type in {"integer", "number", "boolean"}:
            raise exceptions.MalformedSchemaError(
                f"maxLength is not supported for {artifacts.open_api.type}")
        # Must be string type
        if artifacts.open_api.format in {"date", "date-time"}:
            raise exceptions.MalformedSchemaError(
                "maxLength is not supported for string with the format "
                f"{artifacts.open_api.format}")
    if artifacts.extension.autoincrement is not None:
        if artifacts.open_api.type in {"number", "string", "boolean"}:
            raise exceptions.MalformedSchemaError(
                f"autoincrement is not supported for {artifacts.open_api.type}"
            )
    if artifacts.open_api.type == "boolean" and artifacts.open_api.format is not None:
        raise exceptions.MalformedSchemaError(
            "format is not supported for boolean")
Ejemplo n.º 15
0
def _prepare_schema(
    *, schema: types.Schema, schemas: types.Schemas
) -> types.ReadOnlySchema:
    """
    Check and transform readOnly schema to consistent format.

    Args:
        schema: The readOnly schema to operate on.
        schemas: Used to resolve any $ref.
        array_context: Whether checking is being done at the array items level. Changes
            exception messages and schema validation.

    Returns:
        The schema in a consistent format.

    """
    # Check readOnly
    if not helpers.peek.read_only(schema=schema, schemas=schemas):
        raise exceptions.MalformedSchemaError(
            "A readOnly property must set readOnly to True."
        )

    # Check type
    try:
        type_ = helpers.peek.type_(schema=schema, schemas=schemas)
    except exceptions.TypeMissingError:
        raise exceptions.MalformedSchemaError(
            "Every readOnly property must have a type."
        )

    if type_ == "object":
        return _prepare_schema_object(schema=schema, schemas=schemas)
    if type_ == "array":
        return _prepare_schema_array(schema=schema, schemas=schemas)
    raise exceptions.MalformedSchemaError(
        "A readOnly property can only be an object or array."
    )
Ejemplo n.º 16
0
def handle_object_reference(*, spec: types.Schema, schemas: types.Schemas,
                            fk_column: str) -> types.Schema:
    """
    Determine the foreign key schema for an object reference.

    Args:
        spec: The schema of the object reference.
        schemas: All defined schemas.
        fk_column: The foreign column name to use.

    Returns:
        The foreign key schema.

    """
    tablename = helpers.get_ext_prop(source=spec, name="x-tablename")
    if not tablename:
        raise exceptions.MalformedSchemaError(
            "Referenced object is missing x-tablename property.")
    properties = spec.get("properties")
    if properties is None:
        raise exceptions.MalformedSchemaError(
            "Referenced object does not have any properties.")
    fk_logical_name = fk_column if fk_column is not None else "id"
    fk_spec = properties.get(fk_logical_name)
    if fk_spec is None:
        raise exceptions.MalformedSchemaError(
            f"Referenced object does not have {fk_logical_name} property.")
    # Preparing specification
    prepared_fk_spec = helpers.prepare_schema(schema=fk_spec, schemas=schemas)
    fk_type = prepared_fk_spec.get("type")
    if fk_type is None:
        raise exceptions.MalformedSchemaError(
            f"Referenced object {fk_logical_name} property does not have a type."
        )

    return {"type": fk_type, "x-foreign-key": f"{tablename}.{fk_logical_name}"}
Ejemplo n.º 17
0
def _separate_context_path(*, ref: str) -> typing.Tuple[str, str]:
    """
    Separate the context and path of a reference.

    Raise MalformedSchemaError if the reference does not contain #.

    Args:
        ref: The reference to separate.

    Returns:
        The context and path to the schema as a tuple.

    """
    try:
        ref_context, ref_schema = ref.split("#")
    except ValueError:
        raise exceptions.MalformedSchemaError(
            f"A reference must contain exactly one #. Actual reference: {ref}")
    return ref_context, ref_schema
Ejemplo n.º 18
0
def format_(*, schema: types.Schema, schemas: types.Schemas) -> typing.Optional[str]:
    """
    Retrieve the format property from a property schema.

    Raises MalformedSchemaError if the format value is not a string.

    Args:
        schema: The schema to get the format from.
        schemas: The schemas for $ref lookup.

    Returns:
        The format value or None if it was not found.

    """
    value = peek_key(schema=schema, schemas=schemas, key="format")
    if value is None:
        return None
    if not isinstance(value, str):
        raise exceptions.MalformedSchemaError("A format value must be of type string.")
    return value
Ejemplo n.º 19
0
def primary_key(*, schema: types.Schema, schemas: types.Schemas) -> bool:
    """
    Determine whether property schema is for a primary key.

    Raises MalformedSchemaError if the x-primary-key value is not a boolean.

    Args:
        schema: The schema to get x-primary-key from.
        schemas: The schemas for $ref lookup.

    Returns:
        Whether the schema is for a primary key property.

    """
    value = peek_key(schema=schema, schemas=schemas, key="x-primary-key")
    if value is None:
        return False
    if not isinstance(value, bool):
        raise exceptions.MalformedSchemaError(
            "The x-primary-key property must be of type boolean.")
    return value
Ejemplo n.º 20
0
def read_only(*, schema: types.Schema, schemas: types.Schemas) -> bool:
    """
    Determine whether schema is readOnly.

    Raises MalformedSchemaError if the readOnly value is not a boolean.

    Args:
        schema: The schema to get readOnly from.
        schemas: The schemas for $ref lookup.

    Returns:
        Whether the schema is readOnly.

    """
    value = peek_key(schema=schema, schemas=schemas, key="readOnly")
    if value is None:
        return False
    if not isinstance(value, bool):
        raise exceptions.MalformedSchemaError(
            "A readOnly property must be of type boolean.")
    return value
Ejemplo n.º 21
0
def tablename(*, schema: types.Schema, schemas: types.Schemas) -> typing.Optional[str]:
    """
    Retrieve the tablename of the schema.

    Raises MalformedSchemaError if the tablename value is not a string.

    Args:
        schema: The schema to get tablename from.
        schemas: The schemas for $ref lookup.

    Returns:
        The tablename or None.

    """
    value = peek_key(schema=schema, schemas=schemas, key="x-tablename")
    if value is None:
        return None
    if not isinstance(value, str):
        raise exceptions.MalformedSchemaError(
            "The x-tablename property must be of type string."
        )
    return value
Ejemplo n.º 22
0
def default(*, schema: types.Schema,
            schemas: types.Schemas) -> types.TColumnDefault:
    """
    Retrieve the default value and check it against the schema.

    Raises MalformedSchemaError if the default value does not conform with the schema.

    Args:
        schema: The schema to retrieve the default value from.

    Returns:
        The default or None.

    """
    # Retrieve value
    value = peek_key(schema=schema,
                     schemas=schemas,
                     key=types.OpenApiProperties.DEFAULT)
    if value is None:
        return None
    # Assemble schema
    resolved_schema: types.ColumnSchema = {
        types.OpenApiProperties.TYPE.value: type_(schema=schema,
                                                  schemas=schemas)
    }
    format_value = format_(schema=schema, schemas=schemas)
    max_length_value = max_length(schema=schema, schemas=schemas)
    if format_value is not None:
        resolved_schema[types.OpenApiProperties.FORMAT.value] = format_value
    if max_length_value is not None:
        resolved_schema[
            types.OpenApiProperties.MAX_LENGTH.value] = max_length_value
    try:
        jsonschema.validate(value, resolved_schema)
    except jsonschema.ValidationError as exc:
        raise exceptions.MalformedSchemaError(
            "The default value does not conform to the schema. "
            f"The value is: {repr(value)}") from exc
    return value
Ejemplo n.º 23
0
def write_only(*, schema: types.Schema,
               schemas: types.Schemas) -> typing.Optional[bool]:
    """
    Determine whether schema is writeOnly.

    Raises MalformedSchemaError if the writeOnly value is not a boolean.

    Args:
        schema: The schema to get writeOnly from.
        schemas: The schemas for $ref lookup.

    Returns:
        Whether the schema is writeOnly.

    """
    value = peek_key(schema=schema, schemas=schemas, key="writeOnly")
    if value is None:
        return None
    if not isinstance(value, bool):
        raise exceptions.MalformedSchemaError(
            "A writeOnly property must be of type boolean.")
    return value
Ejemplo n.º 24
0
def json(*, schema: types.Schema,
         schemas: types.Schemas) -> typing.Optional[bool]:
    """
    Retrieve the value of the x-json extension property of the schema.

    Raises MalformedSchemaError if the value is not a boolean.

    Args:
        schema: The schema to get x-json from.
        schemas: The schemas for $ref lookup.

    Returns:
        The x-json value or None if the schema does not have the key.

    """
    value = peek_key(schema=schema, schemas=schemas, key="x-json")
    if value is None:
        return None
    if not isinstance(value, bool):
        raise exceptions.MalformedSchemaError(
            "The x-json property must be of type boolean.")
    return value
Ejemplo n.º 25
0
def max_length(*, schema: types.Schema, schemas: types.Schemas) -> typing.Optional[int]:
    """
    Retrieve the maxLength property from a property schema.

    Raises MalformedSchemaError if the maxLength value is not an integer.

    Args:
        schema: The schema to get the maxLength from.
        schemas: The schemas for $ref lookup.

    Returns:
        The maxLength value or None if it was not found.

    """
    value = peek_key(schema=schema, schemas=schemas, key="maxLength")
    if value is None:
        return None
    if not isinstance(value, int):
        raise exceptions.MalformedSchemaError(
            "A maxLength value must be of type integer."
        )
    return value
Ejemplo n.º 26
0
def nullable(*, schema: types.Schema, schemas: types.Schemas) -> typing.Optional[bool]:
    """
    Retrieve the nullable property from a property schema.

    Raises MalformedSchemaError if the nullable value is not a boolean.

    Args:
        schema: The schema to get the nullable from.
        schemas: The schemas for $ref lookup.

    Returns:
        The nullable value.

    """
    value = peek_key(schema=schema, schemas=schemas, key="nullable")
    if value is None:
        return None
    if not isinstance(value, bool):
        raise exceptions.MalformedSchemaError(
            "A nullable value must be of type boolean."
        )
    return value
Ejemplo n.º 27
0
def _prepare_schema_array(
    *, schema: types.Schema, schemas: types.Schemas
) -> types.ReadOnlyArraySchema:
    """
    Check and transform readOnly schema to consistent format.

    Args:
        schema: The readOnly schema to operate on.
        schemas: Used to resolve any $ref.

    Returns:
        The schema in a consistent format.

    """
    schema = helpers.prepare_schema(schema=schema, schemas=schemas)

    items_schema = schema.get("items")
    if items_schema is None:
        raise exceptions.MalformedSchemaError("A readOnly array must define its items.")
    array_object_schema = _prepare_schema_object_common(
        schema=items_schema, schemas=schemas, array_context=True
    )
    return {"type": "array", "readOnly": True, "items": array_object_schema}
Ejemplo n.º 28
0
def dict_ignore(*, schema: types.Schema,
                schemas: types.Schemas) -> typing.Optional[bool]:
    """
    Retrieve the x-dict-ignore property from a property schema.

    Raises MalformedSchemaError if the x-dict-ignore value is not a boolean.

    Args:
        schema: The schema to get the x-dict-ignore from.
        schemas: The schemas for $ref lookup.

    Returns:
        The x-dict-ignore value.

    """
    value = peek_key(schema=schema,
                     schemas=schemas,
                     key=types.ExtensionProperties.DICT_IGNORE)
    if value is None:
        return None
    if not isinstance(value, bool):
        raise exceptions.MalformedSchemaError(
            "A x-dict-ignore value must be of type boolean.")
    return value
Ejemplo n.º 29
0
def server_default(*, schema: types.Schema,
                   schemas: types.Schemas) -> typing.Optional[str]:
    """
    Retrieve the x-server-default property from a property schema.

    Raises MalformedSchemaError if the x-server-default value is not a string.

    Args:
        schema: The schema to get the x-server-default from.
        schemas: The schemas for $ref lookup.

    Returns:
        The x-server-default value.

    """
    value = peek_key(schema=schema,
                     schemas=schemas,
                     key=types.ExtensionProperties.SERVER_DEFAULT)
    if value is None:
        return None
    if not isinstance(value, str):
        raise exceptions.MalformedSchemaError(
            "A x-server-default value must be of type string.")
    return value
Ejemplo n.º 30
0
def foreign_key_column(*, schema: types.Schema,
                       schemas: types.Schemas) -> typing.Optional[str]:
    """
    Retrieve the x-foreign-key-column of the schema.

    Raises MalformedSchemaError if the x-foreign-key-column value is not a string.

    Args:
        schema: The schema to get x-foreign-key-column from.
        schemas: The schemas for $ref lookup.

    Returns:
        The x-foreign-key-column or None.

    """
    value = peek_key(schema=schema,
                     schemas=schemas,
                     key=types.ExtensionProperties.FOREIGN_KEY_COLUMN)
    if value is None:
        return None
    if not isinstance(value, str):
        raise exceptions.MalformedSchemaError(
            "The x-foreign-key-column property must be of type string.")
    return value