diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..47ef7c07f --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +[flake8] +max-line-length = 88 +select = C,E,F,W,B,B9 +ignore = E203, E501, W503 +exclude = __init__.py diff --git a/fastapi/routing.py b/fastapi/routing.py index 5789d1c19..0128b33ce 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -42,10 +42,9 @@ from starlette.types import ASGIApp from starlette.websockets import WebSocket try: - from pydantic.fields import FieldInfo, ModelField + from pydantic.fields import ModelField except ImportError: # pragma: nocover # TODO: remove when removing support for Pydantic < 1.0.0 - from pydantic import Schema as FieldInfo # type: ignore from pydantic.fields import Field as ModelField # type: ignore diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 84ddc4e5a..0d1a5f12f 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -27,7 +27,7 @@ class OAuth2PasswordRequestForm: print(data.client_secret) return data - + It creates the following Form request parameters in your endpoint: grant_type: the OAuth2 spec says it is required and MUST be the fixed string "password". @@ -77,7 +77,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): print(data.client_secret) return data - + It creates the following Form request parameters in your endpoint: grant_type: the OAuth2 spec says it is required and MUST be the fixed string "password". diff --git a/pyproject.toml b/pyproject.toml index 3c10b5925..2eb8c9842 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ test = [ "pytest-cov ==2.10.0", "pytest-asyncio >=0.14.0,<0.15.0", "mypy ==0.782", + "flake8 >=3.8.3,<4.0.0", "black ==19.10b0", "isort >=5.0.6,<6.0.0", "requests >=2.24.0,<3.0.0", diff --git a/scripts/lint.sh b/scripts/lint.sh index 12fb359e4..2e2072cf1 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,5 +4,6 @@ set -e set -x mypy fastapi +flake8 fastapi tests black fastapi tests --check isort fastapi tests docs_src scripts --check-only diff --git a/tests/main.py b/tests/main.py index 35b787056..d5603d0e6 100644 --- a/tests/main.py +++ b/tests/main.py @@ -168,7 +168,7 @@ def get_query_type_optional(query: Optional[int] = None): @app.get("/query/int/default") -def get_query_type_optional(query: int = 10): +def get_query_type_int_default(query: int = 10): return f"foo bar {query}" diff --git a/tests/test_application.py b/tests/test_application.py index fcb77c93e..5ba737307 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -976,8 +976,8 @@ openapi_schema = { }, }, }, - "summary": "Get Query Type Optional", - "operationId": "get_query_type_optional_query_int_default_get", + "summary": "Get Query Type Int Default", + "operationId": "get_query_type_int_default_query_int_default_get", "parameters": [ { "required": False, @@ -1144,7 +1144,7 @@ def test_swagger_ui(): assert response.headers["content-type"] == "text/html; charset=utf-8" assert "swagger-ui-dist" in response.text assert ( - f"oauth2RedirectUrl: window.location.origin + '/docs/oauth2-redirect'" + "oauth2RedirectUrl: window.location.origin + '/docs/oauth2-redirect'" in response.text ) diff --git a/tests/test_dependency_class.py b/tests/test_dependency_class.py index bfe777f52..0233492e6 100644 --- a/tests/test_dependency_class.py +++ b/tests/test_dependency_class.py @@ -59,12 +59,14 @@ async def get_callable_gen_dependency(value: str = Depends(callable_gen_dependen @app.get("/async-callable-dependency") -async def get_callable_dependency(value: str = Depends(async_callable_dependency)): +async def get_async_callable_dependency( + value: str = Depends(async_callable_dependency), +): return value @app.get("/async-callable-gen-dependency") -async def get_callable_gen_dependency( +async def get_async_callable_gen_dependency( value: str = Depends(async_callable_gen_dependency), ): return value diff --git a/tests/test_dependency_contextmanager.py b/tests/test_dependency_contextmanager.py index 847a41dce..3e42b47f7 100644 --- a/tests/test_dependency_contextmanager.py +++ b/tests/test_dependency_contextmanager.py @@ -204,19 +204,19 @@ client = TestClient(app) def test_async_state(): - assert state["/async"] == f"asyncgen not started" + assert state["/async"] == "asyncgen not started" response = client.get("/async") assert response.status_code == 200, response.text - assert response.json() == f"asyncgen started" - assert state["/async"] == f"asyncgen completed" + assert response.json() == "asyncgen started" + assert state["/async"] == "asyncgen completed" def test_sync_state(): - assert state["/sync"] == f"generator not started" + assert state["/sync"] == "generator not started" response = client.get("/sync") assert response.status_code == 200, response.text - assert response.json() == f"generator started" - assert state["/sync"] == f"generator completed" + assert response.json() == "generator started" + assert state["/sync"] == "generator completed" def test_async_raise_other(): @@ -281,15 +281,15 @@ def test_sync_raise(): def test_sync_async_state(): response = client.get("/sync_async") assert response.status_code == 200, response.text - assert response.json() == f"asyncgen started" - assert state["/async"] == f"asyncgen completed" + assert response.json() == "asyncgen started" + assert state["/async"] == "asyncgen completed" def test_sync_sync_state(): response = client.get("/sync_sync") assert response.status_code == 200, response.text - assert response.json() == f"generator started" - assert state["/sync"] == f"generator completed" + assert response.json() == "generator started" + assert state["/sync"] == "generator completed" def test_sync_async_raise_other(): diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index 502f5f04c..3205c4cbf 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -134,7 +134,7 @@ def test_encode_model_with_config(): def test_encode_model_with_alias_raises(): with pytest.raises(ValidationError): - model = ModelWithAlias(foo="Bar") + ModelWithAlias(foo="Bar") def test_encode_model_with_alias(): diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py index e3bd91672..ace6bdef7 100644 --- a/tests/test_request_body_parameters_media_type.py +++ b/tests/test_request_body_parameters_media_type.py @@ -8,6 +8,7 @@ app = FastAPI() media_type = "application/vnd.api+json" + # NOTE: These are not valid JSON:API resources # but they are fine for testing requestBody with custom media_type class Product(BaseModel): diff --git a/tests/test_response_by_alias.py b/tests/test_response_by_alias.py index 8121d7b88..de45e0880 100644 --- a/tests/test_response_by_alias.py +++ b/tests/test_response_by_alias.py @@ -54,17 +54,17 @@ def by_alias_list(): @app.get("/no-alias/dict", response_model=ModelNoAlias) -def by_alias_dict(): +def no_alias_dict(): return {"name": "Foo"} @app.get("/no-alias/model", response_model=ModelNoAlias) -def by_alias_model(): +def no_alias_model(): return ModelNoAlias(name="Foo") @app.get("/no-alias/list", response_model=List[ModelNoAlias]) -def by_alias_list(): +def no_alias_list(): return [{"name": "Foo"}, {"name": "Bar"}] @@ -178,8 +178,8 @@ openapi_schema = { }, "/no-alias/dict": { "get": { - "summary": "By Alias Dict", - "operationId": "by_alias_dict_no_alias_dict_get", + "summary": "No Alias Dict", + "operationId": "no_alias_dict_no_alias_dict_get", "responses": { "200": { "description": "Successful Response", @@ -194,8 +194,8 @@ openapi_schema = { }, "/no-alias/model": { "get": { - "summary": "By Alias Model", - "operationId": "by_alias_model_no_alias_model_get", + "summary": "No Alias Model", + "operationId": "no_alias_model_no_alias_model_get", "responses": { "200": { "description": "Successful Response", @@ -210,15 +210,15 @@ openapi_schema = { }, "/no-alias/list": { "get": { - "summary": "By Alias List", - "operationId": "by_alias_list_no_alias_list_get", + "summary": "No Alias List", + "operationId": "no_alias_list_no_alias_list_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { - "title": "Response By Alias List No Alias List Get", + "title": "Response No Alias List No Alias List Get", "type": "array", "items": { "$ref": "#/components/schemas/ModelNoAlias" diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index a0ae93afa..b7ada7caf 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -28,7 +28,7 @@ def get_current_user(oauth_header: "str" = Security(reusable_oauth2)): @app.post("/login") # Here we use string annotations to test them -def read_current_user(form_data: "OAuth2PasswordRequestFormStrict" = Depends()): +def login(form_data: "OAuth2PasswordRequestFormStrict" = Depends()): return form_data @@ -62,13 +62,13 @@ openapi_schema = { }, }, }, - "summary": "Read Current User", - "operationId": "read_current_user_login_post", + "summary": "Login", + "operationId": "login_login_post", "requestBody": { "content": { "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/Body_read_current_user_login_post" + "$ref": "#/components/schemas/Body_login_login_post" } } }, @@ -92,8 +92,8 @@ openapi_schema = { }, "components": { "schemas": { - "Body_read_current_user_login_post": { - "title": "Body_read_current_user_login_post", + "Body_login_login_post": { + "title": "Body_login_login_post", "required": ["grant_type", "username", "password"], "type": "object", "properties": { diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index e9e6d5d27..ecc766511 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -31,12 +31,12 @@ def get_current_user(oauth_header: Optional[str] = Security(reusable_oauth2)): @app.post("/login") -def read_current_user(form_data: OAuth2PasswordRequestFormStrict = Depends()): +def login(form_data: OAuth2PasswordRequestFormStrict = Depends()): return form_data @app.get("/users/me") -def read_current_user(current_user: Optional[User] = Depends(get_current_user)): +def read_users_me(current_user: Optional[User] = Depends(get_current_user)): if current_user is None: return {"msg": "Create an account first"} return current_user @@ -66,13 +66,13 @@ openapi_schema = { }, }, }, - "summary": "Read Current User", - "operationId": "read_current_user_login_post", + "summary": "Login", + "operationId": "login_login_post", "requestBody": { "content": { "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/Body_read_current_user_login_post" + "$ref": "#/components/schemas/Body_login_login_post" } } }, @@ -88,16 +88,16 @@ openapi_schema = { "content": {"application/json": {"schema": {}}}, } }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", "security": [{"OAuth2": []}], } }, }, "components": { "schemas": { - "Body_read_current_user_login_post": { - "title": "Body_read_current_user_login_post", + "Body_login_login_post": { + "title": "Body_login_login_post", "required": ["grant_type", "username", "password"], "type": "object", "properties": { diff --git a/tests/test_skip_defaults.py b/tests/test_skip_defaults.py index e41d1a286..181fff612 100644 --- a/tests/test_skip_defaults.py +++ b/tests/test_skip_defaults.py @@ -30,14 +30,14 @@ class ModelDefaults(BaseModel): @app.get("/", response_model=Model, response_model_exclude_unset=True) -def get() -> ModelSubclass: +def get_root() -> ModelSubclass: return ModelSubclass(sub={}, y=1, z=0) @app.get( "/exclude_unset", response_model=ModelDefaults, response_model_exclude_unset=True ) -def get() -> ModelDefaults: +def get_exclude_unset() -> ModelDefaults: return ModelDefaults(x=None, y="y") @@ -46,14 +46,14 @@ def get() -> ModelDefaults: response_model=ModelDefaults, response_model_exclude_defaults=True, ) -def get() -> ModelDefaults: +def get_exclude_defaults() -> ModelDefaults: return ModelDefaults(x=None, y="y") @app.get( "/exclude_none", response_model=ModelDefaults, response_model_exclude_none=True ) -def get() -> ModelDefaults: +def get_exclude_none() -> ModelDefaults: return ModelDefaults(x=None, y="y") @@ -63,7 +63,7 @@ def get() -> ModelDefaults: response_model_exclude_unset=True, response_model_exclude_none=True, ) -def get() -> ModelDefaults: +def get_exclude_unset_none() -> ModelDefaults: return ModelDefaults(x=None, y="y") diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index c83af6ca5..5759a93f4 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -8,7 +8,7 @@ items = {"foo": "The Foo Wrestlers"} @app.get("/items/{item_id}") -async def create_item(item_id: str): +async def read_item(item_id: str): if item_id not in items: raise HTTPException( status_code=404, @@ -19,7 +19,7 @@ async def create_item(item_id: str): @app.get("/starlette-items/{item_id}") -async def create_item(item_id: str): +async def read_starlette_item(item_id: str): if item_id not in items: raise StarletteHTTPException(status_code=404, detail="Item not found") return {"item": items[item_id]} @@ -49,8 +49,8 @@ openapi_schema = { }, }, }, - "summary": "Create Item", - "operationId": "create_item_items__item_id__get", + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", "parameters": [ { "required": True, @@ -79,8 +79,8 @@ openapi_schema = { }, }, }, - "summary": "Create Item", - "operationId": "create_item_starlette_items__item_id__get", + "summary": "Read Starlette Item", + "operationId": "read_starlette_item_starlette_items__item_id__get", "parameters": [ { "required": True, diff --git a/tests/test_swagger_ui_init_oauth.py b/tests/test_swagger_ui_init_oauth.py index 371cd72fb..59599341e 100644 --- a/tests/test_swagger_ui_init_oauth.py +++ b/tests/test_swagger_ui_init_oauth.py @@ -18,9 +18,9 @@ def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text print(response.text) - assert f"ui.initOAuth" in response.text - assert f'"appName": "The Predendapp"' in response.text - assert f'"clientId": "the-foo-clients"' in response.text + assert "ui.initOAuth" in response.text + assert '"appName": "The Predendapp"' in response.text + assert '"clientId": "the-foo-clients"' in response.text def test_response(): diff --git a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py index 15836841d..90feb0172 100644 --- a/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py +++ b/tests/test_tutorial/test_async_sql_databases/test_tutorial001.py @@ -126,6 +126,6 @@ def test_create_read(): assert data["text"] == note["text"] assert data["completed"] == note["completed"] assert "id" in data - response = client.get(f"/notes/") + response = client.get("/notes/") assert response.status_code == 200, response.text assert data in response.json() diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index 65629df4b..38c6dbe87 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -128,7 +128,7 @@ name_price_missing = { body_missing = { "detail": [ - {"loc": ["body"], "msg": "field required", "type": "value_error.missing",} + {"loc": ["body"], "msg": "field required", "type": "value_error.missing"} ] } diff --git a/tests/test_ws_router.py b/tests/test_ws_router.py index dd0456127..bd7c3c53d 100644 --- a/tests/test_ws_router.py +++ b/tests/test_ws_router.py @@ -28,7 +28,7 @@ async def routerprefixindex(websocket: WebSocket): @router.websocket("/router2") -async def routerindex(websocket: WebSocket): +async def routerindex2(websocket: WebSocket): await websocket.accept() await websocket.send_text("Hello, router!") await websocket.close()