# Winter
[![Build Status](https://travis-ci.org/WinterFramework/winter.svg?branch=master)](https://travis-ci.org/WinterFramework/winter)
[![codecov](https://codecov.io/gh/WinterFramework/winter/branch/master/graph/badge.svg)](https://codecov.io/gh/WinterFramework/winter)
[![Maintainability](https://api.codeclimate.com/v1/badges/876abe42ca943d9c6014/maintainability)](https://codeclimate.com/github/WinterFramework/winter/maintainability)
[![PyPI version](https://badge.fury.io/py/winter.svg)](https://badge.fury.io/py/winter)
[![Gitter](https://badges.gitter.im/winter-python/community.svg)](https://gitter.im/winter-python/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Web Framework for Python inspired by Spring Framework
# Main features
* Declarative API
* Built around python type annotations
* Automatic OpenAPI (swagger) documentation generation
* Suitable for DDD
* Handling exception without boilerplate in accordance with [RFC 7807](https://tools.ietf.org/html/rfc7807)
# How to use
## Installation
```
pip install winter
```
## Hello world
```python
import winter
@winter.controller
class HelloWorldController:
@winter.route_get('/hello/')
def hello(self):
return f'Hello, world!'
```
To use it with Django:
```python
import winter_django
urlpatterns = [
*winter_django.create_django_urls(HelloWorldController),
]
```
## Todo list CRUD example:
```python
from http import HTTPStatus
from typing import List
from typing import Optional
import winter
import winter.web
from dataclasses import dataclass
from winter.data.pagination import Page
from winter.data.pagination import PagePosition
@dataclass
class NewTodoDTO:
todo: str
@dataclass
class TodoUpdateDTO:
todo: str
@dataclass
class TodoDTO:
todo_index: int
todo: str
@winter.web.problem(status=HTTPStatus.NOT_FOUND)
class NotFoundException(Exception):
def __init__(self, todo_index: int):
self.index = todo_index
todo_list: List[str] = []
@winter.web.controller
@winter.route('todo/')
class TodoController:
@winter.route_post('')
@winter.request_body(argument_name='new_todo_dto')
def create_todo(self, new_todo_dto: NewTodoDTO) -> TodoDTO:
todo_list.append(new_todo_dto.todo)
return self._build_todo_dto(len(todo_list) - 1)
@winter.route_get('{todo_index}/')
def get_todo(self, todo_index: int) -> TodoDTO:
self._check_index(todo_index)
return self._build_todo_dto(todo_index)
@winter.route_get('{?q}')
def get_todo_list(self, page_position: PagePosition, q: Optional[str] = None) -> Page[TodoDTO]:
q = q if q is None else q.lower()
dto_list = [
TodoDTO(todo_index=todo_index, todo=todo)
for todo_index, todo in enumerate(todo_list)
if q is None or q in todo.lower()
]
limit = page_position.limit
offset = page_position.offset
paginated_dto_list = dto_list[offset: offset + limit]
return Page(total_count=len(dto_list), items=paginated_dto_list, position=page_position)
@winter.route_get('{todo_index}/')
@winter.request_body(argument_name='todo_update_dto')
def update_todo(self, todo_index: int, todo_update_dto: TodoUpdateDTO):
self._check_index(todo_index)
todo_list[todo_index] = todo_update_dto.todo
@winter.route_get('{todo_index}/')
def delete_todo(self, todo_index: int):
self._check_index(todo_index)
del todo_list[todo_index]
def _check_index(self, todo_index: int):
if todo_index < 0 or todo_index >= len(todo_list):
raise NotFoundException(todo_index=todo_index)
def _build_todo_dto(self, todo_index: int):
return TodoDTO(todo_index=todo_index, todo=todo_list[todo_index])
```
## Extending Page class
```python
import winter
import winter.web
from dataclasses import dataclass
from winter.data.pagination import Page
from winter.data.pagination import PagePosition
from typing import TypeVar
from typing import Generic
T = TypeVar('T')
@dataclass(frozen=True)
class CustomPage(Page, Generic[T]):
extra_field: str # The field will go to meta JSON response field
@winter.web.controller
class ExampleController:
@winter.route_get('/')
def create_todo(self, page_position: PagePosition) -> CustomPage[int]:
return CustomPage(
# Standard Page fields
total_count=3,
items=[1, 2, 3],
position=page_position,
# Custom fields
extra_field=456,
)
```
## Exception handling
```python
from dataclasses import dataclass
from http import HTTPStatus
from typing import List
from rest_framework.request import Request
import winter
import winter.web
# Minimalist approach. Pointed status and that this exception will be handling automatically. Expected output below:
# {'status': 404, 'type': 'urn:problem-type:todo-not-found', 'title': 'Todo not found', 'detail': 'Incorrect index: 1'}
@winter.web.problem(status=HTTPStatus.NOT_FOUND)
class TodoNotFoundException(Exception):
def __init__(self, invalid_index: int):
self.invalid_index = invalid_index
def __str__(self):
return f'Incorrect index: {self.invalid_index}'
# Extending output using dataclass. Dataclass fields will be added to response body. Expected output below:
# {'status': 404, 'type': 'urn:problem-type:todo-not-found', 'title': 'Todo not found', 'detail': '', 'invalid_index': 1}
@winter.web.problem(status=HTTPStatus.NOT_FOUND)
@dataclass
class TodoNotFoundException(Exception):
invalid_index: int
# When we want to override global handler and customize response body. Expected output below:
# {index: 1, 'message': 'Access denied'}
@dataclass
class ErrorDTO:
index: int
message: str
class TodoNotFoundExceptionCustomHandler(winter.web.ExceptionHandler):
@winter.response_status(HTTPStatus.NOT_FOUND)
def handle(self, request: Request, exception: TodoNotFoundException) -> ErrorDTO:
return ErrorDTO(index=exception.invalid_index, message='Access denied')
todo_list: List[str] = []
@winter.web.controller
class TodoProblemExistsController:
@winter.route_get('global/{todo_index}/')
def get_todo_with_global_handling(self, todo_index: int):
raise TodoNotFoundException(invalid_index=todo_index)
@winter.route_get('custom/{todo_index}/')
@winter.raises(TodoNotFoundException, handler_cls=TodoNotFoundExceptionCustomHandler)
def get_todo_with_custom_handling(self, todo_index: int):
raise TodoNotFoundException(invalid_index=todo_index)
```
## Interceptors
You can define interceptors to pre-handle a web request before it gets to a controller.
The pre_handle method arguments will be injected the same way as it's done in controllers.
It's not supported to return any response from interceptors.
However, the exceptions thrown from within an interceptor will be handled automatically.
```python
from rest_framework.request import Request
import winter
from winter.web import Interceptor
from winter.web import ResponseHeader
class HelloWorldInterceptor(Interceptor):
@winter.response_header('x-hello-world', 'hello_world_header')
def pre_handle(self, request: Request, hello_world_header: ResponseHeader[str]):
if 'hello_world' in request.query_params:
hello_world_header.set('Hello, World!')
```
The only way now to register an interceptor is to define a configurer
(don't forget to import during app initialization) and implement the add_interceptors method.
```python
from winter.web import Configurer
from winter.web import InterceptorRegistry
from .interceptors import HelloWorldInterceptor
class HelloWorldConfigurer(Configurer):
def add_interceptors(self, registry: InterceptorRegistry):
registry.add_interceptor(HelloWorldInterceptor())
```
没有合适的资源?快使用搜索试试~ 我知道了~
PyPI 官网下载 | winter-8.1.3.tar.gz
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 163 浏览量
2022-01-17
11:29:52
上传
评论
收藏 53KB GZ 举报
温馨提示
共178个文件
py:162个
txt:10个
pkg-info:2个
资源来自pypi官网。 资源全名:winter-8.1.3.tar.gz
资源详情
资源评论
资源推荐
收起资源包目录
PyPI 官网下载 | winter-8.1.3.tar.gz (178个子文件)
setup.cfg 67B
MANIFEST.in 49B
LICENSE 1KB
README.md 8KB
PKG-INFO 902B
PKG-INFO 902B
decoder.py 9KB
type_inspection.py 7KB
test_type_inspection.py 7KB
test_query_parameters.py 6KB
repository.py 6KB
test_swagger_auto_schema.py 6KB
media_type.py 6KB
view.py 6KB
test_exception_handling.py 5KB
problem_handling.py 4KB
generation.py 4KB
test_argument_resolver.py 4KB
page_position_argument_resolver.py 4KB
test_controller.py 4KB
encoder.py 4KB
inspectors.py 4KB
__init__.py 4KB
argument_resolver.py 4KB
test_response_schema.py 3KB
throttling.py 3KB
component_method.py 3KB
test_type_utils.py 3KB
controller_with_problem_exceptions.py 3KB
test_path_parameters.py 3KB
query_parameters_argument_resolver.py 3KB
controller_with_exceptions.py 3KB
handlers.py 3KB
page_position_argument_inspector.py 2KB
routing.py 2KB
annotations.py 2KB
component.py 2KB
domain_event_dispatcher.py 2KB
test_throttling.py 2KB
repository.py 2KB
output_processor.py 2KB
annotation_decorator.py 2KB
route.py 2KB
controller_with_response_headers.py 2KB
test_argument_type_info.py 2KB
urls.py 2KB
simple_controller.py 2KB
typing.py 2KB
response_header_annotation.py 2KB
page_serializer.py 2KB
response_header_serializer.py 2KB
__init__.py 1KB
validators.py 1KB
sample_winter_controller.py 1KB
setup.py 1KB
component_method_argument.py 1KB
sort.py 1KB
path_parameters_argument_resolver.py 1KB
domain_event_handler.py 1KB
test_path_parameter_inspector.py 1KB
query_parameters_inspector.py 1KB
test_controller_with_limits.py 1KB
response_header_resolver.py 1KB
limits.py 1KB
test_query_parameter_inspector.py 1KB
utils.py 1KB
page_inspector.py 1KB
path_parameters_inspector.py 1KB
controller_with_throttling.py 1KB
urls.py 1KB
controller_with_serializer.py 1KB
body_argument_resolver.py 1KB
test_build_response_schema.py 1KB
domain_event_subscription.py 1KB
response_header_serializers.py 1KB
output_serializer.py 1KB
page_processor.py 1020B
raises.py 970B
controller_with_query_parameters.py 951B
test_reverse.py 926B
request_body_annotation.py 925B
problem.py 919B
output_processor.py 904B
nested_types.py 856B
controller_with_path_parameters.py 843B
exception_handlers.py 833B
test_get_schema_title.py 831B
__init__.py 823B
request_body_resolver.py 819B
conftest.py 817B
controller_with_request_data.py 794B
test_controller_with_serializer.py 788B
__init__.py 759B
input_serializer.py 742B
controller.py 713B
global_exception.py 707B
__init__.py 705B
default_response_status.py 694B
output_template.py 680B
application.py 654B
共 178 条
- 1
- 2
挣扎的蓝藻
- 粉丝: 13w+
- 资源: 15万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于Python的新能源承载力计算及界面设计源码 - HAINING-DG
- 基于Java的本科探索学习项目设计源码 - 本科探索
- 基于Javascript和Python的微商城项目设计源码 - MicroMall
- 基于Java的网上订餐系统设计源码 - online ordering system
- 基于Javascript的超级美眉网络资源管理应用模块设计源码
- 基于Typescript和PHP的编程知识储备库设计源码 - study-php
- Screenshot_2024-05-28-11-40-58-177_com.tencent.mm.jpg
- 基于Dart的Flutter小提琴调音器APP设计源码 - violinhelper
- 基于JavaScript和CSS的随寻订购网页设计源码 - web-order
- 基于MATLAB的声纹识别系统设计源码 - VoiceprintRecognition
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0