Esempio n. 1
0
def test_format_title_simple():
    problem_type = ProblemType("https://example.com/foo",
                               extension={"bar": {
                                   "type": "string"
                               }})
    assert problem_type.format("test {foo}",
                               {"foo": "bar baz bam"}) == "test bar baz bam"
Esempio n. 2
0
class ProblemDetails:
    def __init__(
        self,
        *,
        problem_type: Optional[ProblemType] = None,
        title: Optional[str] = None,
        detail: Optional[str] = None,
        status: Optional[Union[int, HTTPStatus]] = None,
        **kwargs,
    ):
        self.type = ProblemType() if problem_type is None else problem_type
        self.data = self.validate_data(kwargs)
        if title is None:
            title = self.type.title
        self.title = self.type.format(title, self.data)
        if detail is None:
            detail = self.type.detail
        self.detail = self.type.format(detail, self.data)
        self.status = None if status is None else HTTPStatus(status)

    def __iter__(self):
        yield "type", self.type.identifier
        yield "title", self.title
        yield "detail", self.detail
        yield "status", self.status
        yield from self.data.items()

    def __getattr__(self, item):
        try:
            return self.data[item]
        except KeyError:
            raise AttributeError(f"'{type(self).__name__}' object has no attribute '{item}'")

    def validate_data(self, data):
        return {field: self.type.validate(field, value) for field, value in data.items()}
Esempio n. 3
0
def test_format_title_raises_error_on_incorrect_nested_key():
    nested_schema = {
        "foo": {
            "type": "object",
            "items": {
                "bar": {
                    "type": "string"
                }
            }
        }
    }
    problem_type = ProblemType("https://example.com/foo",
                               extension=nested_schema)
    with pytest.raises(AttributeError) as ex:
        problem_type.format("test {foo.baa}", {"foo": {"bar": "bar baz bam"}})
    assert "object has no attribute 'baa'" in str(ex.value)
Esempio n. 4
0
def test_convert_blank_type_to_dict():
    problem_type = ProblemType()
    assert dict(problem_type) == {
        "identifier": "about:blank",
        "title": "",
        "detail": "",
        "extension": {},
    }
Esempio n. 5
0
def test_format_title_nested():
    nested_schema = {
        "foo": {
            "type": "object",
            "items": {
                "bar": {
                    "type": "string"
                }
            }
        }
    }
    problem_type = ProblemType("https://example.com/foo",
                               extension=nested_schema)
    assert (problem_type.format("test {foo.bar}",
                                {"foo": {
                                    "bar": "bar baz bam"
                                }}) == "test bar baz bam")
Esempio n. 6
0
 def __init__(
     self,
     *,
     problem_type: Optional[ProblemType] = None,
     title: Optional[str] = None,
     detail: Optional[str] = None,
     status: Optional[Union[int, HTTPStatus]] = None,
     **kwargs,
 ):
     self.type = ProblemType() if problem_type is None else problem_type
     self.data = self.validate_data(kwargs)
     if title is None:
         title = self.type.title
     self.title = self.type.format(title, self.data)
     if detail is None:
         detail = self.type.detail
     self.detail = self.type.format(detail, self.data)
     self.status = None if status is None else HTTPStatus(status)
def test_construct_typed_details_with_incorrect_data_wrong_value():
    problem_type = ProblemType(extension={
        "foo": {
            "type": "string"
        },
        "baz": {
            "type": "integer"
        }
    })
    with pytest.raises(ValidationError) as ex:
        ProblemDetails(problem_type=problem_type, foo="bar", baz="123")
    assert "'123' is not of type 'integer'" in str(ex.value)
def test_construct_typed_details_with_incorrect_data_wrong_field():
    problem_type = ProblemType(extension={
        "foo": {
            "type": "string"
        },
        "baz": {
            "type": "integer"
        }
    })
    with pytest.raises(ValueError) as ex:
        ProblemDetails(problem_type=problem_type, foo="bar", baa=123)
    assert "'baa' is not a valid extension member for problem type 'ProblemType'." in str(
        ex.value)
def test_construct_typed_details_with_data():
    problem_type = ProblemType(extension={
        "foo": {
            "type": "string"
        },
        "baz": {
            "type": "integer"
        }
    })
    details = ProblemDetails(problem_type=problem_type, foo="bar", baz=123)
    assert hasattr(details, "foo")
    assert details.foo == "bar"
    assert details.baz == 123
    assert not hasattr(details, "bar")
Esempio n. 10
0
def base_type():
    return ProblemType(
        identifier="//example.com/base",
        title="Base example type",
        detail="This is a base example type, imagine that!",
        extension={
            "foo": {
                "type": "string"
            },
            "bar": {
                "type": "integer"
            }
        },
    )
Esempio n. 11
0
def test_convert_typed_details_with_data_to_dict():
    problem_type = ProblemType(extension={
        "foo": {
            "type": "string"
        },
        "baz": {
            "type": "integer"
        }
    })
    details = ProblemDetails(problem_type=problem_type, foo="bar", baz=123)
    result = dict(details)
    assert result == {
        "type": "about:blank",
        "title": "",
        "detail": "",
        "status": None,
        "foo": "bar",
        "baz": 123,
    }
Esempio n. 12
0
def test_convert_type_to_dict():
    problem_type = ProblemType(
        "https://example.com/foo",
        "Foo problem",
        "Foo fighters attack",
        extension={
            "bar": {},
            "baz": {}
        },
    )
    assert dict(problem_type) == {
        "identifier": "https://example.com/foo",
        "title": "Foo problem",
        "detail": "Foo fighters attack",
        "extension": {
            "bar": {},
            "baz": {}
        },
    }
Esempio n. 13
0
def test_extension_is_rejected_if_not_valid_json_schema():
    with pytest.raises(TypeError) as ex:
        ProblemType(extension={"foo": []})
        assert str(ex).endswith(
            "Extension for field 'foo' needs to be a valid JSON schema.")
Esempio n. 14
0
def test_extension_is_rejected_if_includes_class_attribute_names(input):
    with pytest.raises(ValueError) as ex:
        ProblemType(extension={input: {}})
        assert str(ex).endswith(
            f"Extension member name {input} is not allowed.")
Esempio n. 15
0
def test_construct_blank_type():
    problem_type = ProblemType()
    assert problem_type.identifier == "about:blank"
    assert problem_type.title == ""
    assert problem_type.detail == ""
    assert problem_type.extension == {}
Esempio n. 16
0
def test_rejects_identifier_without_path():
    with pytest.raises(ValueError) as ex:
        ProblemType("https://example.com")
        assert str(ex).endswith("path was required but missing")
Esempio n. 17
0
def test_rejects_unallowed_hostname():
    with pytest.raises(ValueError) as ex:
        ProblemType("https://foo.bar/baz")
        assert str(ex).endswith(
            "Host was required to be one of ['example.com'] but was 'foo.bar'")
Esempio n. 18
0
def test_identifier_inserts_default_scheme_and_host(input, expected):
    problem_type = ProblemType(input)
    assert problem_type.identifier == expected
Esempio n. 19
0
def test_identifier_must_not_be_empty():
    with pytest.raises(ValueError):
        ProblemType(identifier="")
Esempio n. 20
0
def test_convert_blank_type_to_string():
    problem_type = ProblemType()
    assert str(problem_type) == "about:blank"
Esempio n. 21
0
def test_identifier_inserts_default_scheme():
    problem_type = ProblemType("//example.com/baz")
    assert problem_type.identifier == "https://example.com/baz"