def test_register_with_instance(): instance = object() with pytest.raises(ValueError) as exception: Component.register(instance) assert str(exception.value) == f'Need class. Got: {instance}' assert exception.value.args == (f'Need class. Got: {instance}', )
def validate_missing_raises_annotations(): from winter.web.exceptions.problem_annotation import ProblemAnnotation from winter.web.exceptions.raises import ExceptionAnnotation from winter.core import Component all_problem_exception: Set[Type[Exception]] = set() global_exceptions: Set[Type[Exception]] = set() declared_raises_exceptions: Set[Type[Exception]] = set() for cls, component in Component.get_all().items(): if component.annotations.get_one_or_none(ProblemAnnotation): all_problem_exception.add(cls) if component.annotations.get_one_or_none(GlobalExceptionAnnotation): global_exceptions.add(cls) for method_component in component.methods: exception_annotations: Iterable[ ExceptionAnnotation] = method_component.annotations.get( ExceptionAnnotation) for exception_annotation in exception_annotations: declared_raises_exceptions.add( exception_annotation.exception_cls) not_global_exceptions = all_problem_exception - global_exceptions missing_exceptions = not_global_exceptions - declared_raises_exceptions if missing_exceptions: message = ', '.join( exc.__name__ for exc in sorted(missing_exceptions, key=lambda ex: ex.__name__)) raise AssertionError( 'You are missing declaration for next exceptions: ' + message)
def test_global_exception_decorator_declarative_way(): @global_exception class GlobalException(Exception): pass component = Component.get_by_cls(GlobalException) assert component is not None assert component.annotations.get(GlobalExceptionAnnotation) == [GlobalExceptionAnnotation(GlobalException)]
def test_global_exception_decorator_imperative_way(): class GlobalException(Exception): pass register_global_exception(GlobalException) component = Component.get_by_cls(GlobalException) assert component is not None assert component.annotations.get(GlobalExceptionAnnotation) == [GlobalExceptionAnnotation(GlobalException)]
def test_on_class_by_decorator(decorator): @decorator('test') class SimpleComponent: pass assert is_component(SimpleComponent) component = Component.get_by_cls(SimpleComponent) assert component.annotations.get(SimpleAnnotation) == [ SimpleAnnotation('test') ]
def test_resolve_path_parameter(path, arg_name, expected_value): component = Component.get_by_cls(ControllerWithPathParameters) argument = component.get_method('test').get_argument(arg_name) resolver = PathParametersArgumentResolver() request = Mock(spec=Request) request.path_info = path # Act result = resolver.resolve_argument(argument, request, {}) # Assert assert result == expected_value
def autodiscover_problem_annotations(handler_generator: ProblemExceptionHandlerGenerator): handled_problems: Dict[Type[Exception], ProblemAnnotation] = { cls: component.annotations.get_one(ProblemAnnotation) for cls, component in Component.get_all().items() if component.annotations.get_one_or_none(ProblemAnnotation) } for exception_class, problem_annotation in handled_problems.items(): handler_class = handler_generator.generate(exception_class, problem_annotation.handling_info) exception_handlers_registry.add_handler( exception_class, handler_class, auto_handle=True, )
def test_methods(): class SimpleComponent: @winter.core.component_method def simple_method(self): return self component = Component.get_by_cls(SimpleComponent) assert len(component.methods) == 1, SimpleComponent.simple_method method = component.get_method('simple_method') assert method is SimpleComponent.simple_method component = SimpleComponent() assert SimpleComponent.simple_method(component) is component
def generate_problem_handlers(): mapper = ProblemExceptionMapper() handler_generator = ProblemExceptionHandlerGenerator() handled_problems: Dict[Type[Exception], ProblemAnnotation] = { cls: component.annotations.get_one(ProblemAnnotation) for cls, component in Component.get_all().items() if component.annotations.get_one_or_none(ProblemAnnotation) } for exception_class, problem_annotation in handled_problems.items(): handler_class = handler_generator.generate(exception_class, mapper) exception_handlers_registry.add_handler( exception_class, handler_class, auto_handle=problem_annotation.auto_handle, )
def test_empty_annotation(): @annotate(None) class Controller: @annotate(None) def simple_method(self): # pragma: no cover pass component = Component.get_by_cls(Controller) # Assert assert Controller.simple_method.annotations.get_one_or_none(None) is None assert Controller.simple_method.annotations.get_one_or_none( type(None)) is None assert component.annotations.get_one_or_none(None) is None assert component.annotations.get_one_or_none(type(None)) is None
def to_response_body(self, request: Request, exception: Exception) -> Dict: exception_class = exception.__class__ component = Component.get_by_cls(exception_class) annotation = component.annotations.get_one(ProblemAnnotation) assert isinstance(annotation, ProblemAnnotation) problem_dict = dict( status=annotation.status, title=annotation.title or self._generate_default_title_value(exception_class), detail=annotation.detail or str(exception), type=annotation.type or self._generate_type_value(exception_class), ) if dataclasses.is_dataclass(exception.__class__): problem_dict.update(dataclasses.asdict(exception)) return problem_dict
def generate(self, exception_class: Type[Exception], exception_mapper: ExceptionMapper) -> Type[ExceptionHandler]: from winter import response_status component = Component.get_by_cls(exception_class) annotation = component.annotations.get_one(ProblemAnnotation) assert isinstance(annotation, ProblemAnnotation) return_type_class = self._build_exception_dataclass(exception_class) @response_status(annotation.status) def handle_method(self, request: Request, exception: exception_class, **kwargs) -> return_type_class: return exception_mapper.to_response_body(request, exception) handler_class_name = exception_class.__name__ + 'Handler' handler_class = type(handler_class_name, (ExceptionHandler, ), {'handle': handle_method}) return handler_class
def controller(controller_class: Type) -> Type: Component.register(controller_class) return controller_class
def get_component(class_: Type) -> Component: return Component.get_by_cls(class_)
def get_component(controller_class: _ControllerType) -> Component: return Component.get_by_cls(controller_class)