Example #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)
Example #2
0
    def compile(self, obj: object) -> ResponseDescriptionCompiled:
        """`obj` should be a mapping."""

        obj = ensure_mapping(obj)
        compiled = self._default

        status_code_obj = obj.get(_KEY_STATUS_CODE)
        if status_code_obj is not None:
            with on_key(_KEY_STATUS_CODE):
                status_code = self._compile_status_code(status_code_obj)
            compiled = replace(compiled, status_code=status_code)

        headers_obj = obj.get(_KEY_HEADERS)
        if headers_obj is not None:
            with on_key(_KEY_HEADERS):
                headers = self._compile_descriptions(headers_obj)
            compiled = replace(compiled, headers=headers)

        body_obj = obj.get(_KEY_BODY)
        if body_obj is not None:
            with on_key(_KEY_BODY):
                body = self._compile_descriptions(body_obj)
            compiled = replace(compiled, body=body)

        return compiled
Example #3
0
    def compile(
        self,
        obj: object,
        arguments: Optional[Arguments] = None,
    ) -> RequestCompiled:
        """
        Compiles an object into an intermediate request.

        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.
        """
        if isinstance(obj, Argument):
            obj = inject_arguments(obj, arguments)

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

        obj = ensure_mapping(obj)
        compiled = self._default

        method_obj = obj.get(_KEY_METHOD)
        if method_obj is not None:
            with on_key(_KEY_METHOD):
                method_obj = inject_arguments(method_obj, arguments)
                method = _compile_method(method_obj)
            compiled = replace(compiled, method=method)

        path_obj = obj.get(_KEY_PATH)
        if path_obj is not None:
            with on_key(_KEY_PATH):
                path_obj = inject_arguments(path_obj, arguments)
                path = ensure_str(path_obj)
            compiled = replace(compiled, path=path)

        headers_obj = obj.get(_KEY_HEADERS)
        if headers_obj is not None:
            with on_key(_KEY_HEADERS):
                headers_obj = inject_arguments(headers_obj, arguments)
                headers = _compile_headers(headers_obj)
            compiled = replace(compiled, headers=headers)

        params_obj = obj.get(_KEY_PARAMS)
        if params_obj is not None:
            with on_key(_KEY_PARAMS):
                params = compile_url_params(params_obj, arguments)
            compiled = replace(compiled, params=params)

        body_obj = obj.get(_KEY_BODY)
        if body_obj is not None:
            with on_key(_KEY_BODY):
                body = self._body.compile(body_obj, arguments)
            compiled = replace(compiled, body=body)

        return compiled
Example #4
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)
Example #5
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
Example #6
0
 def _compile_recursive(self, key: str, obj: object):
     matcher_func, multiple = self._recursive[key]
     if multiple:
         objs = ensure_list(obj)
         inner_matchers = list(map_compile(self.compile, objs))
     else:
         with on_key(key):
             inner_matchers = [self.compile(obj)]
     return RecursiveMatcherFactory(matcher_func, inner_matchers)
Example #7
0
    def compile_and_replace(self, obj: Mapping) -> RequestBodyCompiled:
        compiled = self

        data_obj = obj.get(_KEY_DATA)
        if data_obj is not None:
            with on_key(_KEY_DATA):
                data = compile_url_params(data_obj)
            compiled = replace(self, data=data)

        return compiled
Example #8
0
    def compile(self, obj: object) -> CaseCompiled:
        """`obj` should be a mapping."""

        obj = ensure_mapping(obj)
        compiled = self._default

        label_obj = obj.get(_KEY_LABEL)
        with on_key(_KEY_LABEL):
            label = ensure_optional_str(label_obj)
            # `label` is always replaced.
            compiled = replace(compiled, label=label)

        enabled_obj = obj.get(_KEY_ENABLED)
        if enabled_obj is not None:
            with on_key(_KEY_ENABLED):
                enabled = ensure_bool(enabled_obj)
            compiled = replace(compiled, enabled=enabled)

        conditions_obj = obj.get(_KEY_CONDITIONS)
        if conditions_obj is not None:
            with on_key(_KEY_CONDITIONS):
                conditions = list(
                    map_compile(
                        self._description.compile,
                        ensure_list(conditions_obj),
                    )
                )
            compiled = replace(compiled, conditions=conditions)

        request_obj = obj.get(_KEY_REQUEST)
        if request_obj is not None:
            with on_key(_KEY_REQUEST):
                request = self._request.compile(request_obj)
            compiled = replace(compiled, request=request)

        response_obj = obj.get(_KEY_RESPONSE)
        if response_obj is not None:
            with on_key(_KEY_RESPONSE):
                response = self._response.compile(response_obj)
            compiled = replace(compiled, response=response)

        return compiled
Example #9
0
    def compile(self, obj: object):
        """`obj` should be a mapping."""

        obj = ensure_mapping(obj)

        extraction_obj = obj.get(_KEY_DESCRIBE)
        with on_key(_KEY_DESCRIBE):
            extractor = self._extraction.compile(extraction_obj)

        predicate_objs = ensure_list(obj.get(_KEY_SHOULD, []))
        with on_key(_KEY_SHOULD):
            predicates = list(
                map_compile(
                    self._predicate.compile,
                    predicate_objs,
                ))

        value_name_obj = obj.get(_KEY_AS)
        with on_key(_KEY_AS):
            value_name = ensure_optional_str(value_name_obj)

        return Description(extractor=extractor,
                           predicates=predicates,
                           value_name=value_name)
Example #10
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)
Example #11
0
    def compile(self,
                obj: object,
                arguments: Optional[Arguments] = None) -> Scenario:
        """
        Compile the given object into a scenario.

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

        obj = ensure_mapping(obj)
        arguments = arguments or {}

        label_obj = inject_arguments(obj.get(_KEY_LABEL), arguments)
        with on_key(_KEY_LABEL):
            label = ensure_optional_str(label_obj)

        parameters_obj = obj.get(_KEY_PARAMETERS)
        if parameters_obj is not None:
            with on_key(_KEY_PARAMETERS):
                parameters_obj = ensure_list(parameters_obj)
                parameters = list(
                    map_compile(compile_parameter, parameters_obj))
            subscenarios = [
                self._compile_parameterized(obj, arguments, parameter)
                for parameter in parameters
            ]
            return Scenario(label=label, subscenarios=subscenarios)

        ordered_obj = inject_arguments(obj.get(_KEY_ORDERED, True), arguments)
        with on_key(_KEY_ORDERED):
            ordered = ensure_bool(ordered_obj)

        default_obj = inject_arguments(obj.get(_KEY_DEFAULT, {}), arguments)
        with on_key(_KEY_DEFAULT):
            case_compiler = self._case.compile_default(default_obj)

        condition_obj = inject_arguments(obj.get(_KEY_WHEN, []), arguments)
        with on_key(_KEY_WHEN):
            conditions = self._compile_conditions(condition_obj)

        case_obj = inject_arguments(obj.get(_KEY_CASES, []), arguments)
        with on_key(_KEY_CASES):
            cases = self._compile_cases(case_compiler, case_obj)

        subscenario_obj = obj.get(_KEY_SUBSCENARIOS, [])
        with on_key(_KEY_SUBSCENARIOS):
            subscenarios = self._compile_subscenarios(
                case_compiler,
                subscenario_obj,
                arguments,
            )

        return Scenario(
            label=label,
            ordered=ordered,
            conditions=conditions,
            cases=cases,
            subscenarios=subscenarios,
        )