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)
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
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
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)
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
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)
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
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
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)
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)
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, )