Exemple #1
0
    def compile(self, obj: object) -> Extractor:
        """`obj` should be a mapping or a string."""

        if isinstance(obj, str):
            return self.compile({_KEY_JQ: obj})

        if not isinstance(obj, Mapping):
            message = f"Must be a map or a string, given {type(obj)}"
            raise CompilationError(message)

        key_candidates = self._factory_map.keys() & obj.keys()
        key_count = len(key_candidates)
        if key_count != 1:
            raise CompilationError(
                f"Must have only 1 extraction key, but has {key_count}")
        factory_key = next(iter(key_candidates))
        factory = self._factory_map[factory_key]
        query = obj[factory_key]

        multiple_obj = obj.get(_KEY_MULTIPLE, False)
        with on_key(_KEY_MULTIPLE):
            multiple = ensure_bool(multiple_obj)

        cast: Optional[Callable[[object], Any]] = None
        cast_obj = obj.get(_KEY_CAST_TO)
        if cast_obj is not None:
            with on_key(_KEY_CAST_TO):
                cast = self._compile_cast(cast_obj)

        return factory(query, multiple=multiple, cast=cast)
Exemple #2
0
def compile_url_params(
    obj: object,
    arguments: Optional[Arguments] = None,
) -> UrlParams:
    """
    Compiles an object into URL parameters.

    Args:
        obj: A compiled object, which should be a mapping or a string.
        arguments: Arguments to inject.
    Returns:
        The result of compilation.
    Raises:
        CompilationError: when compilation fails.
    """
    obj = inject_arguments(obj, arguments)

    if isinstance(obj, str):
        return obj

    if not isinstance(obj, Mapping):
        raise CompilationError("Must be a mapping or a string")

    compiled = {}
    for key, value in obj.items():
        assert isinstance(key, str)  # Satisfied in injecting arguments.
        with on_key(key):
            compiled[key] = compile_url_param(value)
    return compiled
Exemple #3
0
    def compile(
        self,
        obj: object,
        arguments: Optional[Arguments] = None,
    ) -> RequestBodyCompiled:
        """
        Compiles an object into an intermediate request body.

        Args:
            obj: A compiled object, which should be a mapping.
            arguments: Arguments to inject.
        Returns:
            The result of compilation.
        Raises:
            CompilationError: when compilation fails.
        """

        obj = inject_arguments(obj, arguments)
        obj = ensure_mapping(obj)
        compiled = self._default

        type_obj = obj.get(_KEY_TYPE)
        if type_obj is not None:
            with on_key(_KEY_TYPE):
                key = ensure_str(type_obj)
                factory = _TYPE_FACTORY_MAP.get(key)
                if not factory:
                    raise CompilationError(
                        f"Must be in {list(_TYPE_FACTORY_MAP)}"
                        f", but given: {key}")
            compiled = self._default.replace(factory())

        return compiled.compile_and_replace(obj)
Exemple #4
0
    def compile(self, obj: object) -> MatcherFactory:
        """
        Compile an object into a matcher factory.

        Args:
            obj: A compiled object.
        Returns:
            The result of compilation.
        Raises:
            CompilationError: when compilation fails.
        """

        if isinstance(obj, str) and obj in self._static:
            return self._static[obj]

        if isinstance(obj, Mapping):
            if len(obj) != 1:
                message = f"Must have only 1 element, but has {len(obj)}"
                raise CompilationError(message)

            key, value_obj = next(iter(obj.items()))
            if key in self._taking_value:
                return self._compile_taking_value(key, value_obj)
            if key in self._recursive:
                return self._compile_recursive(key, value_obj)

        return ValueMatcherFactory(hamcrest.equal_to, StaticValue(obj))
Exemple #5
0
def _compile_method(obj: object) -> Method:
    key = ensure_str(obj).upper()
    method = _METHOD_MAP.get(key)
    if not method:
        message = f"Must be in {list(_METHOD_MAP)}, but given: {obj}"
        raise CompilationError(message)
    return method
Exemple #6
0
def test_response_compilation_fails(compiler: CaseCompiler, res):
    res.compile.side_effect = CompilationError("msg", node=NamedNode("bar"))
    with raises(CompilationError) as error_info:
        compiler.compile({"response": "res"})
    assert error_info.value.path == [NamedNode("response"), NamedNode("bar")]

    res.compile.assert_called_once_with("res")
Exemple #7
0
def test_request_compilation_fails(compiler: CaseCompiler, req):
    req.compile.side_effect = CompilationError("msg", node=NamedNode("foo"))
    with raises(CompilationError) as error_info:
        compiler.compile({"request": "/path"})
    assert error_info.value.path == [NamedNode("request"), NamedNode("foo")]

    req.compile.assert_called_once_with("/path")
Exemple #8
0
def test_conditions_compilation_fails(compiler: CaseCompiler, desc):
    desc.compile.side_effect = CompilationError("msg", node=NamedNode("foo"))
    with raises(CompilationError) as error_info:
        compiler.compile({"when": "xxx"})
    assert error_info.value.path == [NamedNode("when"), IndexedNode(0), NamedNode("foo")]

    desc.compile.assert_called_once_with("xxx")
def test_given_invalid_body(compiler: RequestCompiler, body):
    body.compile.side_effect = CompilationError("x", node=IndexedNode(1))

    with raises(CompilationError) as error_info:
        compiler.compile({"body": sentinel.body_obj})
    assert error_info.value.path == [NamedNode("body"), IndexedNode(1)]

    body.compile.assert_called_once_with(sentinel.body_obj, None)
Exemple #10
0
def test_when_parameter_compilation_fails(compiler: ScenarioCompiler, mocker):
    compile_parameter = mocker.patch(f"{PKG}.compile_parameter")
    compile_parameter.side_effect = CompilationError("message")

    with raises(CompilationError) as error_info:
        compiler.compile({"parameters": [sentinel.param_obj]})
    assert error_info.value.path == [NamedNode("parameters"), IndexedNode(0)]

    compile_parameter.assert_called_once_with(sentinel.param_obj)
Exemple #11
0
def test_map_compile_for_failing_func():
    child_error = CompilationError("message", node=NamedNode("key"))
    failing_func = Mock(side_effect=[1, child_error, 2])
    results = map_compile(failing_func, [3, 4, 5])
    assert next(results) == 1
    with raises(CompilationError) as error_info:
        next(results)
    assert error_info.value.path == [IndexedNode(1), NamedNode("key")]
    failing_func.assert_has_calls([call(3), call(4)])
Exemple #12
0
    def _compile_cast(obj: object) -> Callable[[object], Any]:
        """`obj` should be a string."""

        key = ensure_str(obj)
        cast = _CAST_FUNC_MAP.get(key)
        if not cast:
            raise CompilationError(f"Invalid value: {key}")

        return cast
def test_given_an_invalid_params(compiler: RequestCompiler, mocker):
    compile_params = mocker.patch(f"{PKG}.compile_url_params")
    compile_params.side_effect = CompilationError("msg", node=NamedNode("x"))

    with raises(CompilationError) as error_info:
        compiler.compile({"params": sentinel.params})
    assert error_info.value.path == [NamedNode("params"), NamedNode("x")]

    compile_params.assert_called_once_with(sentinel.params, None)
Exemple #14
0
def test_compile_and_replace_given_invalid_data(mocker):
    compile_params = mocker.patch(f"{PKG}.compile_url_params")
    compile_params.side_effect = CompilationError("m", node=NamedNode("x"))

    default = UrlencodedRequestBodyCompiled(data=sentinel.original_data)
    with raises(CompilationError) as error_info:
        default.compile_and_replace({"data": sentinel.data})
    assert error_info.value.path == [NamedNode("data"), NamedNode("x")]

    compile_params.assert_called_once_with(sentinel.data)
Exemple #15
0
def test_render_path():
    error = CompilationError("message")
    assert error.path == []
    assert error.render_path() == ""
    assert render_path(error.path) == ""

    error = error.on_node(IndexedNode(1))
    assert error.path == [IndexedNode(1)]
    assert error.render_path() == "[1]"
    assert render_path(error.path) == "[1]"

    error = CompilationError("message", node=None, child=error)
    assert error.path == [IndexedNode(1)]
    assert error.render_path() == "[1]"
    assert render_path(error.path) == "[1]"

    error = error.on_node(NamedNode("foo"))
    assert error.path == [NamedNode("foo"), IndexedNode(1)]
    assert error.render_path() == ".foo[1]"
    assert render_path(error.path) == ".foo[1]"
Exemple #16
0
def compile_url_param(value: object) -> UrlParam:
    if value is None:
        return value
    if isinstance(value, list):
        return list(map_compile(compile_url_param_value, value))
    try:
        return compile_url_param_value(value)
    except CompilationError as error:
        raise CompilationError(
            f"Not allowed type for a request parameter: {value.__class__}",
            cause=error,
        )
Exemple #17
0
def ensure_bool(obj: object) -> bool:
    """
    Ensure a boolean object.

    Args:
        obj: An ensured object, which should be a `bool` value.
    Returns:
        The compiled value.
    Raises:
        CompilationError: when compilation fails.
    """
    if not isinstance(obj, bool):
        raise CompilationError(f"Must be a boolean, given {type(obj)}")
    return obj
Exemple #18
0
def ensure_mapping(obj: object) -> Mapping:
    """
    Ensure a mapping object.

    Args:
        obj: A compiled object, which should be a mapping.
    Returns:
        The compile result.
    Raises:
        CompilationError: when compilation fails.
    """
    if not isinstance(obj, Mapping):
        raise CompilationError(f"Must be a map, given {type(obj)}")
    return obj
Exemple #19
0
def ensure_str(obj: object) -> str:
    """
    Ensure a string object.

    Args:
        obj: An ensured object, which should be a `string` value.
    Returns:
        The compiled value.
    Raises:
        CompilationError: when compilation fails.
    """
    if not isinstance(obj, str):
        raise CompilationError(f"must be a string, given {type(obj)}")
    return obj
Exemple #20
0
def compile_url_param_value(value: object) -> object:
    if isinstance(value, Value):
        return value

    if value is None:
        return value
    if isinstance(value, bool):
        return value
    if isinstance(value, int):
        return value
    if isinstance(value, float):
        return value
    if isinstance(value, str):
        return value
    if isinstance(value, date):
        return value
    raise CompilationError(
        f"Not allowed type for a request parameter value: {value.__class__}")
Exemple #21
0
 def _func(value):
     if value == "_error":
         raise CompilationError("message")
Exemple #22
0
 def _compile(flag: bool) -> bool:
     if not flag:
         raise CompilationError("msg", node=NamedNode("x"))
     return not flag
Exemple #23
0
 def _func(key: object, value: object) -> object:
     if not isinstance(key, str):
         message = f"Key must be a string, given {type(key)}: {key}"
         raise CompilationError(message)
     with on_key(key):
         return run_recursively(func, value)