diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb701e151..94016ad31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.12 + rev: v0.13.0 hooks: - id: ruff args: diff --git a/README.md b/README.md index 6f13f9eae..a8a0e37b5 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The key features are: * estimation based on tests on an internal development team, building production applications. -## Sponsors { #sponsors } +## Sponsors @@ -67,7 +67,7 @@ The key features are: Other sponsors -## Opinions { #opinions } +## Opinions "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" @@ -113,7 +113,7 @@ The key features are: --- -## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis } +## **Typer**, the FastAPI of CLIs @@ -121,14 +121,14 @@ If you are building a CLI app to be **Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 -## Requirements { #requirements } +## Requirements FastAPI stands on the shoulders of giants: * Starlette for the web parts. * Pydantic for the data parts. -## Installation { #installation } +## Installation Create and activate a virtual environment and then install FastAPI: @@ -144,9 +144,9 @@ $ pip install "fastapi[standard]" **Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. -## Example { #example } +## Example -### Create it { #create-it } +### Create it Create a file `main.py` with: @@ -197,7 +197,7 @@ If you don't know, check the _"In a hurry?"_ section about -### Check it { #check-it } +### Check it Open your browser at http://127.0.0.1:8000/items/5?q=somequery. @@ -256,7 +256,7 @@ You already created an API that: * The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. * The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. -### Interactive API docs { #interactive-api-docs } +### Interactive API docs Now go to http://127.0.0.1:8000/docs. @@ -264,7 +264,7 @@ You will see the automatic interactive API documentation (provided by http://127.0.0.1:8000/redoc. @@ -272,7 +272,7 @@ You will see the alternative automatic documentation (provided by http://127.0.0.1:8000/docs. @@ -326,7 +326,7 @@ Now go to http://127.0.0.1:8000/redoc. @@ -334,7 +334,7 @@ And now, go to one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) To understand more about it, see the section Benchmarks. -## Dependencies { #dependencies } +## Dependencies FastAPI depends on Pydantic and Starlette. -### `standard` Dependencies { #standard-dependencies } +### `standard` Dependencies When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies: @@ -476,15 +476,15 @@ Used by FastAPI: * `fastapi-cli[standard]` - to provide the `fastapi` command. * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. -### Without `standard` Dependencies { #without-standard-dependencies } +### Without `standard` Dependencies If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. -### Without `fastapi-cloud-cli` { #without-fastapi-cloud-cli } +### Without `fastapi-cloud-cli` If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. -### Additional Optional Dependencies { #additional-optional-dependencies } +### Additional Optional Dependencies There are some additional dependencies you might want to install. @@ -498,6 +498,6 @@ Additional optional FastAPI dependencies: * orjson - Required if you want to use `ORJSONResponse`. * ujson - Required if you want to use `UJSONResponse`. -## License { #license } +## License This project is licensed under the terms of the MIT license. diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md new file mode 100644 index 000000000..4a5e5392c --- /dev/null +++ b/docs/de/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM-Testdatei { #llm-test-file } + +Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachspezifische Prompt wird an `general_prompt` angehängt. + +Hier hinzugefügte Tests werden von allen Erstellern sprachspezifischer Prompts gesehen. + +So verwenden: + +* Einen sprachspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. +* Eine frische Übersetzung dieses Dokuments in die gewünschte Zielsprache durchführen (siehe z. B. das Kommando `translate-page` der `translate.py`). Dadurch wird die Übersetzung unter `docs/{language code}/docs/_llm-test.md` erstellt. +* Prüfen Sie, ob in der Übersetzung alles in Ordnung ist. +* Verbessern Sie bei Bedarf Ihren sprachsspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. +* Beheben Sie anschließend manuell die verbleibenden Probleme in der Übersetzung, sodass es eine gute Übersetzung ist. +* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachsspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass LLMs keine deterministischen Algorithmen sind). + +Die Tests: + +## Codeschnipsel { #code-snippets} + +//// tab | Test + +Dies ist ein Codeschnipsel: `foo`. Und dies ist ein weiteres Codeschnipsel: `bar`. Und noch eins: `baz quux`. + +//// + +//// tab | Info + +Der Inhalt von Codeschnipseln sollte unverändert bleiben. + +Siehe Abschnitt `### Content of code snippets` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Anführungszeichen { #quotes } + +//// tab | Test + +Gestern schrieb mein Freund: „Wenn man unkorrekt korrekt schreibt, hat man es unkorrekt geschrieben“. Worauf ich antwortete: „Korrekt, aber ‚unkorrekt‘ ist unkorrekterweise nicht ‚„unkorrekt“‘“. + +/// note | Hinweis + +Das LLM wird dies wahrscheinlich falsch übersetzen. Interessant ist nur, ob es die korrigierte Übersetzung bei einer erneuten Übersetzung beibehält. + +/// + +//// + +//// tab | Info + +Der Prompt-Designer kann entscheiden, ob neutrale Anführungszeichen in typografische Anführungszeichen umgewandelt werden sollen. Es ist in Ordnung, sie unverändert zu lassen. + +Siehe zum Beispiel den Abschnitt `### Quotes` in `docs/de/llm-prompt.md`. + +//// + +## Anführungszeichen in Codeschnipseln { #quotes-in-code-snippets} + +//// tab | Test + +`pip install "foo[bar]"` + +Beispiele für Stringliterale in Codeschnipseln: `"this"`, `'that'`. + +Ein schwieriges Beispiel für Stringliterale in Codeschnipseln: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... Allerdings müssen Anführungszeichen in Codeschnipseln unverändert bleiben. + +//// + +## Codeblöcke { #code-blocks } + +//// tab | Test + +Ein Bash-Codebeispiel ... + +```bash +# Eine Begrüßung an das Universum ausgeben +echo "Hello universe" +``` + +... und ein Konsolen-Codebeispiel ... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +... und noch ein Konsolen-Codebeispiel ... + +```console +// Ein Verzeichnis „Code“ erstellen +$ mkdir code +// In dieses Verzeichnis wechseln +$ cd code +``` + +... und ein Python-Codebeispiel ... + +```Python +wont_work() # Das wird nicht funktionieren 😱 +works(foo="bar") # Das funktioniert 🎉 +``` + +... und das war's. + +//// + +//// tab | Info + +Code in Codeblöcken sollte nicht verändert werden, mit Ausnahme von Kommentaren. + +Siehe Abschnitt `### Content of code blocks` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Tabs und farbige Boxen { #tabs-and-colored-boxes } + +//// tab | Test + +/// info | Info +Etwas Text +/// + +/// note | Hinweis +Etwas Text +/// + +/// note | Technische Details +Etwas Text +/// + +/// check | Testen +Etwas Text +/// + +/// tip | Tipp +Etwas Text +/// + +/// warning | Achtung +Etwas Text +/// + +/// danger | Gefahr +Etwas Text +/// + +//// + +//// tab | Info + +Tabs und `Info`/`Note`/`Warning`/usw. Blöcke sollten die Übersetzung ihres Titels nach einem vertikalen Strich (`|`) erhalten. + +Siehe die Abschnitte `### Special blocks` und `### Tab blocks` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Web- und interne Links { #web-and-internal-links } + +//// tab | Test + +Der Linktext sollte übersetzt werden, die Linkadresse sollte unverändert bleiben: + +* [Link zur Überschrift oben](#code-snippets) +* [Interner Link](index.md#installation){.internal-link target=_blank} +* Externer Link +* Link zu einem Stil +* Link zu einem Skript +* Link zu einem Bild + +Der Linktext sollte übersetzt werden, die Linkadresse sollte auf die Übersetzung zeigen: + +* FastAPI-Link + +//// + +//// tab | Info + +Links sollten übersetzt werden, aber ihre Adresse soll unverändert bleiben. Eine Ausnahme sind absolute Links zu Seiten der FastAPI-Dokumentation. In diesem Fall sollte auf die Übersetzung verlinkt werden. + +Siehe Abschnitt `### Links` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## HTML „abbr“-Elemente { #html-abbr-elements } + +//// tab | Test + +Hier einige Dinge, die in HTML-„abbr“-Elemente gepackt sind (einige sind erfunden): + +### Das abbr gibt eine vollständige Phrase { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Das abbr gibt eine Erklärung { #the-abbr-gives-an-explanation } + +* Cluster +* Deep Learning + +### Das abbr gibt eine vollständige Phrase und eine Erklärung { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +„title“-Attribute von „abbr“-Elementen werden nach bestimmten Anweisungen übersetzt. + +Übersetzungen können eigene „abbr“-Elemente hinzufügen, die das LLM nicht entfernen soll. Z. B. um englische Wörter zu erklären. + +Siehe Abschnitt `### HTML abbr elements` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Überschriften { #headings } + +//// tab | Test + +### Eine Webapp entwickeln – ein Tutorial { #develop-a-webapp-a-tutorial } + +Hallo. + +### Typhinweise und -annotationen { #type-hints-and-annotations } + +Hallo wieder. + +### Super- und Subklassen { #super-and-subclasses } + +Hallo wieder. + +//// + +//// tab | Info + +Die einzige strenge Regel für Überschriften ist, dass das LLM den Hash-Teil in geschweiften Klammern unverändert lässt, damit Links nicht kaputtgehen. + +Siehe Abschnitt `### Headings` im allgemeinen Prompt in `scripts/translate.py`. + +Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. + +//// + +## In der Dokumentation verwendete Begriffe { #terms-used-in-the-docs } + +//// tab | Test + +* Sie +* Ihr + +* z. B. +* usw. + +* `foo` vom Typ `int` +* `bar` vom Typ `str` +* `baz` vom Typ `list` + +* das Tutorial – Benutzerhandbuch +* das Handbuch für fortgeschrittene Benutzer +* die SQLModel-Dokumentation +* die API-Dokumentation +* die automatische Dokumentation + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic-Authentifizierung +* HTTP Digest +* ISO-Format +* der JSON-Schema-Standard +* das JSON-Schema +* die Schema-Definition +* Password Flow +* Mobile + +* deprecatet +* designt +* ungültig +* on the fly +* Standard +* Default +* Groß-/Klein­schrei­bung ist relevant +* Groß-/Klein­schrei­bung ist nicht relevant + +* die Anwendung bereitstellen +* die Seite ausliefern + +* die App +* die Anwendung + +* der Request +* die Response +* die Error-Response + +* die Pfadoperation +* der Pfadoperation-Dekorator +* die Pfadoperation-Funktion + +* der Body +* der Requestbody +* der Responsebody +* der JSON-Body +* der Formularbody +* der Dateibody +* der Funktionskörper + +* der Parameter +* der Body-Parameter +* der Pfad-Parameter +* der Query-Parameter +* der Cookie-Parameter +* der Header-Parameter +* der Formular-Parameter +* der Funktionsparameter + +* das Event +* das Startup-Event +* das Hochfahren des Servers +* das Shutdown-Event +* das Lifespan-Event + +* der Handler +* der Eventhandler +* der Exceptionhandler +* handhaben + +* das Modell +* das Pydantic-Modell +* das Datenmodell +* das Datenbankmodell +* das Formularmodell +* das Modellobjekt + +* die Klasse +* die Basisklasse +* die Elternklasse +* die Subklasse +* die Kindklasse +* die Geschwisterklasse +* die Klassenmethode + +* der Header +* die Header +* der Autorisierungsheader +* der `Authorization`-Header +* der Forwarded-Header + +* das Dependency-Injection-System +* die Dependency +* das Dependable +* der Dependant + +* I/O-lastig +* CPU-lastig +* Nebenläufigkeit +* Parallelität +* Multiprocessing + +* die Umgebungsvariable +* die Umgebungsvariable +* der `PATH` +* die `PATH`-Umgebungsvariable + +* die Authentifizierung +* der Authentifizierungsanbieter +* die Autorisierung +* das Anmeldeformular +* der Autorisierungsanbieter +* der Benutzer authentisiert sich +* das System authentifiziert den Benutzer + +* Das CLI +* Das Kommandozeileninterface + +* der Server +* der Client + +* der Cloudanbieter +* der Clouddienst + +* die Entwicklung +* die Entwicklungsphasen + +* das Dict +* das Dictionary +* die Enumeration +* das Enum +* das Enum-Member + +* der Encoder +* der Decoder +* kodieren +* dekodieren + +* die Exception +* werfen + +* der Ausdruck +* die Anweisung + +* das Frontend +* das Backend + +* die GitHub-Diskussion +* das GitHub-Issue + +* die Leistung +* die Leistungsoptimierung + +* der Rückgabetyp +* der Rückgabewert + +* die Sicherheit +* das Sicherheitsschema + +* der Task +* der Hintergrundtask +* die Taskfunktion + +* das Template +* die Template-Engine + +* die Typannotation +* der Typhinweis + +* der Serverworker +* der Uvicorn-Worker +* der Gunicorn-Worker +* der Workerprozess +* die Workerklasse +* die Workload + +* das Deployment +* bereitstellen + +* das SDK +* das Software Development Kit + +* der `APIRouter` +* die `requirements.txt` +* das Bearer-Token +* der Breaking Change +* der Bug +* der Button +* das Callable +* der Code +* der Commit +* der Contextmanager +* die Coroutine +* die Datenbank-Session +* die Festplatte +* die Domain +* die Engine +* das Fake-X +* die HTTP-GET-Methode +* das Item +* die Bibliothek +* der Lifespan +* der Lock +* die Middleware +* die Mobile-Anwendung +* das Modul +* das Mounten +* das Netzwerk +* das Origin +* Die Überschreibung +* die Payload +* der Prozessor +* die Property +* der Proxy +* der Pull Request +* die Query +* der RAM +* der entfernte Rechner +* der Statuscode +* der String +* der Tag +* das Webframework +* die Wildcard +* zurückgeben +* validieren + +//// + +//// tab | Info + +Dies ist eine nicht vollständige und nicht normative Liste von (meist) technischen Begriffen, die in der Dokumentation vorkommen. Sie kann dem Prompt-Designer helfen herauszufinden, bei welchen Begriffen das LLM Unterstützung braucht. Zum Beispiel, wenn es eine gute Übersetzung immer wieder auf eine suboptimale Übersetzung zurücksetzt. Oder wenn es Probleme hat, einen Begriff in Ihrer Sprache zu konjugieren/deklinieren. + +Siehe z. B. den Abschnitt `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. + +//// diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md new file mode 100644 index 000000000..e72450b91 --- /dev/null +++ b/docs/en/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM test file { #llm-test-file } + +This document tests if the LLM, which translates the documentation, understands the `general_prompt` in `scripts/translate.py` and the language specific prompt in `docs/{language code}/llm-prompt.md`. The language specific prompt is appended to `general_prompt`. + +Tests added here will be seen by all designers of language specific prompts. + +Use as follows: + +* Have a language specific prompt – `docs/{language code}/llm-prompt.md`. +* Do a fresh translation of this document into your desired target language (see e.g. the `translate-page` command of the `translate.py`). This will create the translation under `docs/{language code}/docs/_llm-test.md`. +* Check if things are okay in the translation. +* If necessary, improve your language specific prompt, the general prompt, or the English document. +* Then manually fix the remaining issues in the translation, so that it is a good translation. +* Retranslate, having the good translation in place. The ideal result would be that the LLM makes no changes anymore to the translation. That means that the general prompt and your language specific prompt are as good as they can be (It will sometimes make a few seemingly random changes, the reason is that LLMs are not deterministic algorithms). + +The tests: + +## Code snippets { #code-snippets} + +//// tab | Test + +This is a code snippet: `foo`. And this is another code snippet: `bar`. And another one: `baz quux`. + +//// + +//// tab | Info + +Content of code snippets should be left as is. + +See section `### Content of code snippets` in the general prompt in `scripts/translate.py`. + +//// + +## Quotes { #quotes } + +//// tab | Test + +Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". + +/// note + +The LLM will probably translate this wrong. Interesting is only if it keeps the fixed translation when retranslating. + +/// + +//// + +//// tab | Info + +The prompt designer may choose if they want to convert neutral quotes to typographic quotes. It is okay to leave them as is. + +See for example section `### Quotes` in `docs/de/llm-prompt.md`. + +//// + +## Quotes in code snippets { #quotes-in-code-snippets} + +//// tab | Test + +`pip install "foo[bar]"` + +Examples for string literals in code snippets: `"this"`, `'that'`. + +A difficult example for string literals in code snippets: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... However, quotes inside code snippets must stay as is. + +//// + +## code blocks { #code-blocks } + +//// tab | Test + +A Bash code example... + +```bash +# Print a greeting to the universe +echo "Hello universe" +``` + +...and a console code example... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...and another console code example... + +```console +// Create a directory "Code" +$ mkdir code +// Switch into that directory +$ cd code +``` + +...and a Python code example... + +```Python +wont_work() # This won't work 😱 +works(foo="bar") # This works 🎉 +``` + +...and that's it. + +//// + +//// tab | Info + +Code in code blocks should not be modified, with the exception of comments. + +See section `### Content of code blocks` in the general prompt in `scripts/translate.py`. + +//// + +## Tabs and colored boxes { #tabs-and-colored-boxes } + +//// tab | Test + +/// info +Some text +/// + +/// note +Some text +/// + +/// note | Technical details +Some text +/// + +/// check +Some text +/// + +/// tip +Some text +/// + +/// warning +Some text +/// + +/// danger +Some text +/// + +//// + +//// tab | Info + +Tabs and `Info`/`Note`/`Warning`/etc. blocks should have the translation of their title added after a vertical bar (`|`). + +See sections `### Special blocks` and `### Tab blocks` in the general prompt in `scripts/translate.py`. + +//// + +## Web- and internal links { #web-and-internal-links } + +//// tab | Test + +The link text should get translated, the link address should remain unchaged: + +* [Link to heading above](#code-snippets) +* [Internal link](index.md#installation){.internal-link target=_blank} +* External link +* Link to a style +* Link to a script +* Link to an image + +The link text should get translated, the link address should point to the translation: + +* FastAPI link + +//// + +//// tab | Info + +Links should be translated, but their address shall remain unchanged. An exception are absolute links to pages of the FastAPI documentation. In that case it should link to the translation. + +See section `### Links` in the general prompt in `scripts/translate.py`. + +//// + +## HTML "abbr" elements { #html-abbr-elements } + +//// tab | Test + +Here some things wrapped in HTML "abbr" elements (Some are invented): + +### The abbr gives a full phrase { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### The abbr gives an explanation { #the-abbr-gives-an-explanation } + +* cluster +* Deep Learning + +### The abbr gives a full phrase and an explanation { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +"title" attributes of "abbr" elements are translated following some specific instructions. + +Translations can add their own "abbr" elements which the LLM should not remove. E.g. to explain English words. + +See section `### HTML abbr elements` in the general prompt in `scripts/translate.py`. + +//// + +## Headings { #headings } + +//// tab | Test + +### Develop a webapp - a tutorial { #develop-a-webapp-a-tutorial } + +Hello. + +### Type hints and -annotations { #type-hints-and-annotations } + +Hello again. + +### Super- and subclasses { #super-and-subclasses } + +Hello again. + +//// + +//// tab | Info + +The only hard rule for headings is that the LLM leaves the hash part inside curly brackets unchanged, which ensures that links do not break. + +See section `### Headings` in the general prompt in `scripts/translate.py`. + +For some language specific instructions, see e.g. section `### Headings` in `docs/de/llm-prompt.md`. + +//// + +## Terms used in the docs { #terms-used-in-the-docs } + +//// tab | Test + +* you +* your + +* e.g. +* etc. + +* `foo` as an `int` +* `bar` as a `str` +* `baz` as a `list` + +* the Tutorial - User guide +* the Advanced User Guide +* the SQLModel docs +* the API docs +* the automatic docs + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic authentication +* HTTP Digest +* ISO format +* the JSON Schema standard +* the JSON schema +* the schema definition +* Password Flow +* Mobile + +* deprecated +* designed +* invalid +* on the fly +* standard +* default +* case-sensitive +* case-insensitive + +* to serve the application +* to serve the page + +* the app +* the application + +* the request +* the response +* the error response + +* the path operation +* the path operation decorator +* the path operation function + +* the body +* the request body +* the response body +* the JSON body +* the form body +* the file body +* the function body + +* the parameter +* the body parameter +* the path parameter +* the query parameter +* the cookie parameter +* the header parameter +* the form parameter +* the function parameter + +* the event +* the startup event +* the startup of the server +* the shutdown event +* the lifespan event + +* the handler +* the event handler +* the exception handler +* to handle + +* the model +* the Pydantic model +* the data model +* the database model +* the form model +* the model object + +* the class +* the base class +* the parent class +* the subclass +* the child class +* the sibling class +* the class method + +* the header +* the headers +* the authorization header +* the `Authorization` header +* the forwarded header + +* the dependency injection system +* the dependency +* the dependable +* the dependant + +* I/O bound +* CPU bound +* concurrency +* parallelism +* multiprocessing + +* the env var +* the environment variable +* the `PATH` +* the `PATH` variable + +* the authentication +* the authentication provider +* the authorization +* the authorization form +* the authorization provider +* the user authenticates +* the system authenticates the user + +* the CLI +* the command line interface + +* the server +* the client + +* the cloud provider +* the cloud service + +* the development +* the development stages + +* the dict +* the dictionary +* the enumeration +* the enum +* the enum member + +* the encoder +* the decoder +* to encode +* to decode + +* the exception +* to raise + +* the expression +* the statement + +* the frontend +* the backend + +* the GitHub discussion +* the GitHub issue + +* the performance +* the performance optimization + +* the return type +* the return value + +* the security +* the security scheme + +* the task +* the background task +* the task function + +* the template +* the template engine + +* the type annotation +* the type hint + +* the server worker +* the Uvicorn worker +* the Gunicorn Worker +* the worker process +* the worker class +* the workload + +* the deployment +* to deploy + +* the SDK +* the software development kit + +* the `APIRouter` +* the `requirements.txt` +* the Bearer Token +* the breaking change +* the bug +* the button +* the callable +* the code +* the commit +* the context manager +* the coroutine +* the database session +* the disk +* the domain +* the engine +* the fake X +* the HTTP GET method +* the item +* the library +* the lifespan +* the lock +* the middleware +* the mobile application +* the module +* the mounting +* the network +* the origin +* the override +* the payload +* the processor +* the property +* the proxy +* the pull request +* the query +* the RAM +* the remote machine +* the status code +* the string +* the tag +* the web framework +* the wildcard +* to return +* to validate + +//// + +//// tab | Info + +This is a not complete and not normative list of (mostly) technical terms seen in the docs. It may be helpful for the prompt designer to figure out for which terms the LLM needs a helping hand. For example when it keeps reverting a good translation to a suboptimal translation. Or when it has problems conjugating/declinating a term in your language. + +See e.g. section `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. + +//// diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md index 7b6f08371..e920e22c3 100644 --- a/docs/en/docs/advanced/async-tests.md +++ b/docs/en/docs/advanced/async-tests.md @@ -94,6 +94,6 @@ As the testing function is now asynchronous, you can now also call (and `await`) /// tip -If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using MongoDB's MotorClient), remember to instantiate objects that need an event loop only within async functions, e.g. an `'@app.on_event("startup")` callback. +If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using MongoDB's MotorClient), remember to instantiate objects that need an event loop only within async functions, e.g. an `@app.on_event("startup")` callback. /// diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md index 5473d939c..0f3d8b701 100644 --- a/docs/en/docs/advanced/custom-response.md +++ b/docs/en/docs/advanced/custom-response.md @@ -221,7 +221,7 @@ Takes an async generator or a normal generator/iterator and streams the response #### Using `StreamingResponse` with file-like objects { #using-streamingresponse-with-file-like-objects } -If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object. +If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object. That way, you don't have to read it all first in memory, and you can pass that generator function to the `StreamingResponse`, and return it. diff --git a/docs/en/docs/advanced/response-headers.md b/docs/en/docs/advanced/response-headers.md index 98747eabd..19c9ff2ad 100644 --- a/docs/en/docs/advanced/response-headers.md +++ b/docs/en/docs/advanced/response-headers.md @@ -36,6 +36,6 @@ And as the `Response` can be used frequently to set headers and cookies, **FastA ## Custom Headers { #custom-headers } -Keep in mind that custom proprietary headers can be added using the 'X-' prefix. +Keep in mind that custom proprietary headers can be added using the `X-` prefix. But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in Starlette's CORS docs. diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md index 4ba24637f..917dd79bd 100644 --- a/docs/en/docs/advanced/websockets.md +++ b/docs/en/docs/advanced/websockets.md @@ -2,9 +2,9 @@ You can use WebSockets with **FastAPI**. -## Install `WebSockets` { #install-websockets } +## Install `websockets` { #install-websockets } -Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `websockets`: +Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `websockets` (a Python library that makes it easy to use the "WebSocket" protocol):
diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index a1de2dc46..6b71f7360 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -490,7 +490,7 @@ And normally this **load balancer** would be able to handle requests that go to In this type of scenario, you probably would want to have **a single (Uvicorn) process per container**, as you would already be handling replication at the cluster level. -So, in this case, you **would not** want to have a multiple workers in the container, for example with the `--workers` command line option.You would want to have just a **single Uvicorn process** per container (but probably multiple containers). +So, in this case, you **would not** want to have a multiple workers in the container, for example with the `--workers` command line option. You would want to have just a **single Uvicorn process** per container (but probably multiple containers). Having another process manager inside the container (as would be with multiple workers) would only add **unnecessary complexity** that you are most probably already taking care of with your cluster system. diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index 681caac35..d44d7a6ac 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -190,7 +190,7 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on * **No brainfuck**: * No new schema definition micro-language to learn. * If you know Python types you know how to use Pydantic. -* Plays nicely with your **IDE/linter/brain**: +* Plays nicely with your **IDE/linter/brain**: * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data. * Validate **complex structures**: * Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc. diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md index b38c4ec02..91228c8c9 100644 --- a/docs/en/docs/how-to/custom-docs-ui-assets.md +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -89,7 +89,7 @@ Your new file structure could look like this: Download the static files needed for the docs and put them on that `static/` directory. -You can probably right-click each link and select an option similar to `Save link as...`. +You can probably right-click each link and select an option similar to "Save link as...". **Swagger UI** uses the files: diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 728586497..2cf52b730 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,30 @@ hide: ## Latest Changes +### Refactors + +* 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Upgrades + +* ⬆️ Update mypy to 1.14.1. PR [#12970](https://github.com/fastapi/fastapi/pull/12970) by [@tamird](https://github.com/tamird). + +### Docs + +* 📝 Fix and Improve English Documentation. PR [#14048](https://github.com/fastapi/fastapi/pull/14048) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). +* 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.116.2 + +### Upgrades + +* ⬆️ Upgrade Starlette supported version range to >=0.40.0,<0.49.0. PR [#14077](https://github.com/fastapi/fastapi/pull/14077) by [@musicinmybrain](https://github.com/musicinmybrain). + ### Docs * 📝 Add documentation for Behind a Proxy - Proxy Forwarded Headers, using `--forwarded-allow-ips="*"`. PR [#14028](https://github.com/fastapi/fastapi/pull/14028) by [@tiangolo](https://github.com/tiangolo). @@ -35,6 +59,8 @@ hide: ### Internal +* ⬆ Bump pyjwt from 2.8.0 to 2.9.0. PR [#13960](https://github.com/fastapi/fastapi/pull/13960) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14080](https://github.com/fastapi/fastapi/pull/14080) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/setup-python from 5 to 6. PR [#14042](https://github.com/fastapi/fastapi/pull/14042) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/labeler from 5 to 6. PR [#14046](https://github.com/fastapi/fastapi/pull/14046) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14056](https://github.com/fastapi/fastapi/pull/14056) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index ab6d7461a..ed23c8149 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -119,7 +119,7 @@ For example: /// info -`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later. +`Body` also has all the same extra validation and metadata parameters as `Query`, `Path` and others you will see later. /// diff --git a/docs/en/docs/tutorial/debugging.md b/docs/en/docs/tutorial/debugging.md index a096763f0..08b440084 100644 --- a/docs/en/docs/tutorial/debugging.md +++ b/docs/en/docs/tutorial/debugging.md @@ -62,7 +62,7 @@ from myapp import app # Some more code ``` -in that case, the automatically created variable inside of `myapp.py` will not have the variable `__name__` with a value of `"__main__"`. +in that case, the automatically created variable `__name__` inside of `myapp.py` will not have the value `"__main__"`. So, the line: diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md index 9bfbf47c9..bc0519c67 100644 --- a/docs/en/docs/tutorial/middleware.md +++ b/docs/en/docs/tutorial/middleware.md @@ -35,7 +35,7 @@ The middleware function receives: /// tip -Keep in mind that custom proprietary headers can be added using the 'X-' prefix. +Keep in mind that custom proprietary headers can be added using the `X-` prefix. But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in Starlette's CORS docs. diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md index 435606bbf..ef1caea42 100644 --- a/docs/en/docs/tutorial/path-params-numeric-validations.md +++ b/docs/en/docs/tutorial/path-params-numeric-validations.md @@ -2,7 +2,7 @@ In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`. -## Import Path { #import-path } +## Import `Path` { #import-path } First, import `Path` from `fastapi`, and import `Annotated`: diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md index a55b4cfb0..adf08a924 100644 --- a/docs/en/docs/tutorial/query-params-str-validations.md +++ b/docs/en/docs/tutorial/query-params-str-validations.md @@ -250,14 +250,10 @@ q: str | None = None But we are now declaring it with `Query`, for example like: -//// tab | Annotated - ```Python q: Annotated[str | None, Query(min_length=3)] = None ``` -//// - So, when you need to declare a value as required while using `Query`, you can simply not declare a default value: {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} diff --git a/docs/en/docs/tutorial/sql-databases.md b/docs/en/docs/tutorial/sql-databases.md index 79538e566..cfa1c9073 100644 --- a/docs/en/docs/tutorial/sql-databases.md +++ b/docs/en/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Here we'll see an example using "ORMs"), FastAPI doesn't force you to use anything. 😎 +You could use any other SQL or NoSQL database library you want (in some cases called "ORMs"), FastAPI doesn't force you to use anything. 😎 /// diff --git a/docs_src/handling_errors/tutorial005.py b/docs_src/handling_errors/tutorial005.py index 6e0b81d31..0e04fa086 100644 --- a/docs_src/handling_errors/tutorial005.py +++ b/docs_src/handling_errors/tutorial005.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI, Request, status +from fastapi import FastAPI, Request from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse @@ -10,7 +10,7 @@ app = FastAPI() @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): return JSONResponse( - status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + status_code=422, content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), ) diff --git a/fastapi/__init__.py b/fastapi/__init__.py index b02bf8b4f..9342f1add 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.116.1" +__version__ = "0.116.2" from starlette import status as status diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 451ea0760..0ad548b94 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -241,6 +241,7 @@ def jsonable_encoder( sqlalchemy_safe=sqlalchemy_safe, ) if dataclasses.is_dataclass(obj): + assert not isinstance(obj, type) obj_dict = dataclasses.asdict(obj) return jsonable_encoder( obj_dict, diff --git a/fastapi/exception_handlers.py b/fastapi/exception_handlers.py index 6c2ba7fed..475dd7bdd 100644 --- a/fastapi/exception_handlers.py +++ b/fastapi/exception_handlers.py @@ -5,7 +5,7 @@ from fastapi.websockets import WebSocket from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import JSONResponse, Response -from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY, WS_1008_POLICY_VIOLATION +from starlette.status import WS_1008_POLICY_VIOLATION async def http_exception_handler(request: Request, exc: HTTPException) -> Response: @@ -21,7 +21,7 @@ async def request_validation_exception_handler( request: Request, exc: RequestValidationError ) -> JSONResponse: return JSONResponse( - status_code=HTTP_422_UNPROCESSABLE_ENTITY, + status_code=422, content={"detail": jsonable_encoder(exc.errors())}, ) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..eda64a999 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -35,7 +35,6 @@ from fastapi.utils import ( from pydantic import BaseModel from starlette.responses import JSONResponse from starlette.routing import BaseRoute -from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY from typing_extensions import Literal validation_error_definition = { @@ -416,7 +415,7 @@ def get_openapi_path( ) deep_dict_update(openapi_response, process_response) openapi_response["description"] = description - http422 = str(HTTP_422_UNPROCESSABLE_ENTITY) + http422 = "422" all_route_params = get_flat_params(route.dependant) if (all_route_params or route.body_field) and not any( status in operation["responses"] diff --git a/fastapi/routing.py b/fastapi/routing.py index 54c75a027..5418ad982 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -120,6 +120,7 @@ def _prepare_response_content( for k, v in res.items() } elif dataclasses.is_dataclass(res): + assert not isinstance(res, type) return dataclasses.asdict(res) return res diff --git a/pyproject.toml b/pyproject.toml index 7709451ff..6ec72374c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.40.0,<0.48.0", + "starlette>=0.40.0,<0.49.0", "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0", "typing-extensions>=4.8.0", ] @@ -60,7 +60,7 @@ Changelog = "https://fastapi.tiangolo.com/release-notes/" standard = [ "fastapi-cli[standard] >=0.0.8", # For the test client - "httpx >=0.23.0", + "httpx >=0.23.0,<1.0.0", # For templates "jinja2 >=3.1.5", # For forms and file uploads @@ -79,7 +79,7 @@ standard = [ standard-no-fastapi-cloud-cli = [ "fastapi-cli[standard-no-fastapi-cloud-cli] >=0.0.8", # For the test client - "httpx >=0.23.0", + "httpx >=0.23.0,<1.0.0", # For templates "jinja2 >=3.1.5", # For forms and file uploads @@ -98,7 +98,7 @@ standard-no-fastapi-cloud-cli = [ all = [ "fastapi-cli[standard] >=0.0.8", # # For the test client - "httpx >=0.23.0", + "httpx >=0.23.0,<1.0.0", # For templates "jinja2 >=3.1.5", # For forms and file uploads diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index f9a490975..c1107b9b0 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests -httpx >=0.23.0,<0.29.0 +httpx >=0.23.0,<1.0.0 # For linting and generating docs versions ruff ==0.12.7 diff --git a/requirements-github-actions.txt b/requirements-github-actions.txt index f807d06a8..a6a733447 100644 --- a/requirements-github-actions.txt +++ b/requirements-github-actions.txt @@ -1,6 +1,6 @@ PyGithub>=2.3.0,<3.0.0 pydantic>=2.5.3,<3.0.0 pydantic-settings>=2.1.0,<3.0.0 -httpx>=0.27.0,<0.29.0 +httpx>=0.27.0,<1.0.0 pyyaml >=5.3.1,<7.0.0 smokeshow diff --git a/requirements-tests.txt b/requirements-tests.txt index b9f2b2b66..e87a42162 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -2,12 +2,12 @@ -r requirements-docs-tests.txt pytest >=7.1.3,<9.0.0 coverage[toml] >= 6.5.0,< 8.0 -mypy ==1.8.0 +mypy ==1.14.1 dirty-equals ==0.9.0 sqlmodel==0.0.24 flask >=1.1.2,<4.0.0 anyio[trio] >=3.2.1,<5.0.0 -PyJWT==2.8.0 +PyJWT==2.9.0 pyyaml >=5.3.1,<7.0.0 passlib[bcrypt] >=1.7.2,<2.0.0 inline-snapshot>=0.21.1 diff --git a/scripts/docs.py b/scripts/docs.py index 8462e2bc1..56ffb9d36 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -44,6 +44,8 @@ en_config_path: Path = en_docs_path / mkdocs_name site_path = Path("site").absolute() build_site_path = Path("site_build").absolute() +header_with_permalink_pattern = re.compile(r"^(#{1,6}) (.+?)(\s*\{\s*#.*\s*\})\s*$") + @lru_cache def is_mkdocs_insiders() -> bool: @@ -154,9 +156,21 @@ index_sponsors_template = """ """ +def remove_header_permalinks(content: str): + lines: list[str] = [] + for line in content.split("\n"): + match = header_with_permalink_pattern.match(line) + if match: + hashes, title, *_ = match.groups() + line = f"{hashes} {title}" + lines.append(line) + return "\n".join(lines) + + def generate_readme_content() -> str: en_index = en_docs_path / "docs" / "index.md" content = en_index.read_text("utf-8") + content = remove_header_permalinks(content) # remove permalinks from headers match_pre = re.search(r"\n\n", content) match_start = re.search(r"", content) match_end = re.search(r"", content) diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index 30329282f..2e5ac6c06 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -102,7 +102,7 @@ def test_schema(): def test_get_invalid(): response = client.get("/foo") - assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + assert response.status_code == 422 def test_get_valid():