mirror of https://github.com/tiangolo/fastapi.git
🏁 Update Windows development environment and tests (#1179)
* 🏁 Fix ./scripts/docs.py encoding for Windows * 🔥 Remove ujson from tests as it prevents Windows development It's still tested by Starlette anyway * 📝 Update development instructions for Windows * 🎨 Update format for WSGIMiddleware example * ✅ Update tests to run on Windows
This commit is contained in:
parent
56e43ba204
commit
459f0e11e5
|
|
@ -12,7 +12,7 @@ Then wrap the WSGI (e.g. Flask) app with the middleware.
|
||||||
|
|
||||||
And then mount that under a path.
|
And then mount that under a path.
|
||||||
|
|
||||||
```Python hl_lines="1 3 22"
|
```Python hl_lines="2 3 22"
|
||||||
{!../../../docs_src/wsgi/tutorial001.py!}
|
{!../../../docs_src/wsgi/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,13 +113,25 @@ $ flit install --deps develop --symlink
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
If you are on Windows, use `--pth-file` instead of `--symlink`:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ flit install --deps develop --pth-file
|
||||||
|
|
||||||
|
---> 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
It will install all the dependencies and your local FastAPI in your local environment.
|
It will install all the dependencies and your local FastAPI in your local environment.
|
||||||
|
|
||||||
#### Using your local FastAPI
|
#### Using your local FastAPI
|
||||||
|
|
||||||
If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code.
|
If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code.
|
||||||
|
|
||||||
And if you update that local FastAPI source code, as it is installed with `--symlink`, when you run that Python file again, it will use the fresh version of FastAPI you just edited.
|
And if you update that local FastAPI source code, as it is installed with `--symlink` (or `--pth-file` on Windows), when you run that Python file again, it will use the fresh version of FastAPI you just edited.
|
||||||
|
|
||||||
That way, you don't have to "install" your local version to be able to test every change.
|
That way, you don't have to "install" your local version to be able to test every change.
|
||||||
|
|
||||||
|
|
@ -137,17 +149,7 @@ $ bash scripts/format.sh
|
||||||
|
|
||||||
It will also auto-sort all your imports.
|
It will also auto-sort all your imports.
|
||||||
|
|
||||||
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above:
|
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `--symlink` (or `--pth-file` on Windows).
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ flit install --symlink
|
|
||||||
|
|
||||||
---> 100%
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### Format imports
|
### Format imports
|
||||||
|
|
||||||
|
|
@ -293,7 +295,7 @@ $ python ./scripts/docs.py live es
|
||||||
|
|
||||||
Now you can go to <a href="http://127.0.0.1:8008" class="external-link" target="_blank">http://127.0.0.1:8008</a> and see your changes live.
|
Now you can go to <a href="http://127.0.0.1:8008" class="external-link" target="_blank">http://127.0.0.1:8008</a> and see your changes live.
|
||||||
|
|
||||||
If you look at the FastAPI docs website, you will see that every language has all the pages. But some are not translated and have a notification about the the translation is missing.
|
If you look at the FastAPI docs website, you will see that every language has all the pages. But some pages are not translated and have a notification about the missing translation.
|
||||||
|
|
||||||
But when you run it locally like this, you will only see the pages that are already translated.
|
But when you run it locally like this, you will only see the pages that are already translated.
|
||||||
|
|
||||||
|
|
@ -474,10 +476,10 @@ This command generates a directory `./htmlcov/`, if you open the file `./htmlcov
|
||||||
|
|
||||||
### Tests in your editor
|
### Tests in your editor
|
||||||
|
|
||||||
If you want to use the integrated tests in your editor add `./docs/src` to your `PYTHONPATH` variable.
|
If you want to use the integrated tests in your editor add `./docs_src` to your `PYTHONPATH` variable.
|
||||||
|
|
||||||
For example, in VS Code you can create a file `.env` with:
|
For example, in VS Code you can create a file `.env` with:
|
||||||
|
|
||||||
```env
|
```env
|
||||||
PYTHONPATH=./docs/src
|
PYTHONPATH=./docs_src
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from flask import Flask, escape, request
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.wsgi import WSGIMiddleware
|
from fastapi.middleware.wsgi import WSGIMiddleware
|
||||||
|
from flask import Flask, escape, request
|
||||||
|
|
||||||
flask_app = Flask(__name__)
|
flask_app = Flask(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ test = [
|
||||||
"async_generator",
|
"async_generator",
|
||||||
"python-multipart",
|
"python-multipart",
|
||||||
"aiofiles",
|
"aiofiles",
|
||||||
"ujson",
|
|
||||||
"flask"
|
"flask"
|
||||||
]
|
]
|
||||||
doc = [
|
doc = [
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ def new_lang(lang: str = typer.Argument(..., callback=lang_callback)):
|
||||||
new_path.mkdir()
|
new_path.mkdir()
|
||||||
en_docs_path = Path("docs/en")
|
en_docs_path = Path("docs/en")
|
||||||
en_config_path: Path = en_docs_path / mkdocs_name
|
en_config_path: Path = en_docs_path / mkdocs_name
|
||||||
en_config: dict = mkdocs.utils.yaml_load(en_config_path.read_text())
|
en_config: dict = mkdocs.utils.yaml_load(en_config_path.read_text(encoding="utf-8"))
|
||||||
fastapi_url_base = "https://fastapi.tiangolo.com/"
|
fastapi_url_base = "https://fastapi.tiangolo.com/"
|
||||||
new_config = {}
|
new_config = {}
|
||||||
new_config["site_name"] = en_config["site_name"]
|
new_config["site_name"] = en_config["site_name"]
|
||||||
|
|
@ -90,14 +90,16 @@ def new_lang(lang: str = typer.Argument(..., callback=lang_callback)):
|
||||||
extra_js.append(fastapi_url_base + js)
|
extra_js.append(fastapi_url_base + js)
|
||||||
new_config["extra_javascript"] = extra_js
|
new_config["extra_javascript"] = extra_js
|
||||||
new_config_path: Path = Path(new_path) / mkdocs_name
|
new_config_path: Path = Path(new_path) / mkdocs_name
|
||||||
new_config_path.write_text(yaml.dump(new_config, sort_keys=False, width=200))
|
new_config_path.write_text(
|
||||||
|
yaml.dump(new_config, sort_keys=False, width=200), encoding="utf-8"
|
||||||
|
)
|
||||||
new_config_docs_path: Path = new_path / "docs"
|
new_config_docs_path: Path = new_path / "docs"
|
||||||
new_config_docs_path.mkdir()
|
new_config_docs_path.mkdir()
|
||||||
en_index_path: Path = en_docs_path / "docs" / "index.md"
|
en_index_path: Path = en_docs_path / "docs" / "index.md"
|
||||||
new_index_path: Path = new_config_docs_path / "index.md"
|
new_index_path: Path = new_config_docs_path / "index.md"
|
||||||
en_index_content = en_index_path.read_text()
|
en_index_content = en_index_path.read_text(encoding="utf-8")
|
||||||
new_index_content = f"{missing_translation_snippet}\n\n{en_index_content}"
|
new_index_content = f"{missing_translation_snippet}\n\n{en_index_content}"
|
||||||
new_index_path.write_text(new_index_content)
|
new_index_path.write_text(new_index_content, encoding="utf-8")
|
||||||
typer.secho(f"Successfully initialized: {new_path}", color=typer.colors.GREEN)
|
typer.secho(f"Successfully initialized: {new_path}", color=typer.colors.GREEN)
|
||||||
update_languages(lang=None)
|
update_languages(lang=None)
|
||||||
|
|
||||||
|
|
@ -128,10 +130,12 @@ def build_lang(
|
||||||
shutil.rmtree(build_lang_path, ignore_errors=True)
|
shutil.rmtree(build_lang_path, ignore_errors=True)
|
||||||
shutil.copytree(lang_path, build_lang_path)
|
shutil.copytree(lang_path, build_lang_path)
|
||||||
en_config_path: Path = en_lang_path / mkdocs_name
|
en_config_path: Path = en_lang_path / mkdocs_name
|
||||||
en_config: dict = mkdocs.utils.yaml_load(en_config_path.read_text())
|
en_config: dict = mkdocs.utils.yaml_load(en_config_path.read_text(encoding="utf-8"))
|
||||||
nav = en_config["nav"]
|
nav = en_config["nav"]
|
||||||
lang_config_path: Path = lang_path / mkdocs_name
|
lang_config_path: Path = lang_path / mkdocs_name
|
||||||
lang_config: dict = mkdocs.utils.yaml_load(lang_config_path.read_text())
|
lang_config: dict = mkdocs.utils.yaml_load(
|
||||||
|
lang_config_path.read_text(encoding="utf-8")
|
||||||
|
)
|
||||||
lang_nav = lang_config["nav"]
|
lang_nav = lang_config["nav"]
|
||||||
# Exclude first 2 entries FastAPI and Languages, for custom handling
|
# Exclude first 2 entries FastAPI and Languages, for custom handling
|
||||||
use_nav = nav[2:]
|
use_nav = nav[2:]
|
||||||
|
|
@ -146,9 +150,9 @@ def build_lang(
|
||||||
en_file_path: Path = en_lang_path / "docs" / file_path
|
en_file_path: Path = en_lang_path / "docs" / file_path
|
||||||
lang_file_path.parent.mkdir(parents=True, exist_ok=True)
|
lang_file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
if not lang_file_path.is_file():
|
if not lang_file_path.is_file():
|
||||||
en_text = en_file_path.read_text()
|
en_text = en_file_path.read_text(encoding="utf-8")
|
||||||
lang_text = get_text_with_translate_missing(en_text)
|
lang_text = get_text_with_translate_missing(en_text)
|
||||||
lang_file_path.write_text(lang_text)
|
lang_file_path.write_text(lang_text, encoding="utf-8")
|
||||||
file_key = file_to_nav[file]
|
file_key = file_to_nav[file]
|
||||||
use_lang_file_to_nav[file] = file_key
|
use_lang_file_to_nav[file] = file_key
|
||||||
if file_key:
|
if file_key:
|
||||||
|
|
@ -171,7 +175,7 @@ def build_lang(
|
||||||
lang_config["nav"] = export_lang_nav
|
lang_config["nav"] = export_lang_nav
|
||||||
build_lang_config_path: Path = build_lang_path / mkdocs_name
|
build_lang_config_path: Path = build_lang_path / mkdocs_name
|
||||||
build_lang_config_path.write_text(
|
build_lang_config_path.write_text(
|
||||||
yaml.dump(lang_config, sort_keys=False, width=200)
|
yaml.dump(lang_config, sort_keys=False, width=200), encoding="utf-8"
|
||||||
)
|
)
|
||||||
current_dir = os.getcwd()
|
current_dir = os.getcwd()
|
||||||
os.chdir(build_lang_path)
|
os.chdir(build_lang_path)
|
||||||
|
|
@ -272,7 +276,7 @@ def live(
|
||||||
def update_config(lang: str):
|
def update_config(lang: str):
|
||||||
lang_path: Path = docs_path / lang
|
lang_path: Path = docs_path / lang
|
||||||
config_path = lang_path / mkdocs_name
|
config_path = lang_path / mkdocs_name
|
||||||
config: dict = mkdocs.utils.yaml_load(config_path.read_text())
|
config: dict = mkdocs.utils.yaml_load(config_path.read_text(encoding="utf-8"))
|
||||||
languages = [{"en": "/"}]
|
languages = [{"en": "/"}]
|
||||||
for lang in docs_path.iterdir():
|
for lang in docs_path.iterdir():
|
||||||
if lang.name == "en" or not lang.is_dir():
|
if lang.name == "en" or not lang.is_dir():
|
||||||
|
|
@ -280,7 +284,9 @@ def update_config(lang: str):
|
||||||
name = lang.name
|
name = lang.name
|
||||||
languages.append({name: f"/{name}/"})
|
languages.append({name: f"/{name}/"})
|
||||||
config["nav"][1] = {"Languages": languages}
|
config["nav"][1] = {"Languages": languages}
|
||||||
config_path.write_text(yaml.dump(config, sort_keys=False, width=200))
|
config_path.write_text(
|
||||||
|
yaml.dump(config, sort_keys=False, width=200), encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_key_section(
|
def get_key_section(
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,4 @@ def test_get_timed():
|
||||||
response = client.get("/timed")
|
response = client.get("/timed")
|
||||||
assert response.json() == {"message": "It's the time of my life"}
|
assert response.json() == {"message": "It's the time of my life"}
|
||||||
assert "X-Response-Time" in response.headers
|
assert "X-Response-Time" in response.headers
|
||||||
assert float(response.headers["X-Response-Time"]) > 0
|
assert float(response.headers["X-Response-Time"]) >= 0
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
from fastapi.testclient import TestClient
|
|
||||||
|
|
||||||
from custom_response.tutorial001 import app
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
openapi_schema = {
|
|
||||||
"openapi": "3.0.2",
|
|
||||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
|
||||||
"paths": {
|
|
||||||
"/items/": {
|
|
||||||
"get": {
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Successful Response",
|
|
||||||
"content": {"application/json": {"schema": {}}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"summary": "Read Items",
|
|
||||||
"operationId": "read_items_items__get",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_openapi_schema():
|
|
||||||
response = client.get("/openapi.json")
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.json() == openapi_schema
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_custom_response():
|
|
||||||
response = client.get("/items/")
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.json() == [{"item_id": "Foo"}]
|
|
||||||
Loading…
Reference in New Issue