mirror of
https://github.com/fastapi/fastapi.git
synced 2026-01-14 08:58:09 -05:00
Compare commits
24 Commits
0.128.0
...
fastapi-to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4cc90e8f9 | ||
|
|
ea059d18be | ||
|
|
f2687dc1bb | ||
|
|
862c3f4f94 | ||
|
|
052d6e86c2 | ||
|
|
31c7ffcdfe | ||
|
|
6854be9ebc | ||
|
|
258deb925d | ||
|
|
53d2453d1a | ||
|
|
d9b7b65b81 | ||
|
|
9ed5f246ed | ||
|
|
edf7995775 | ||
|
|
47391ea8fb | ||
|
|
3b1b4f034b | ||
|
|
f362fdc234 | ||
|
|
4ce34686d9 | ||
|
|
dbe83f3919 | ||
|
|
13743e115a | ||
|
|
52842fb8d3 | ||
|
|
4d4fb28f9f | ||
|
|
a1735d6d11 | ||
|
|
1b42639296 | ||
|
|
ded035a421 | ||
|
|
44c849c4fc |
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -8,7 +8,7 @@ updates:
|
||||
commit-message:
|
||||
prefix: ⬆
|
||||
# Python
|
||||
- package-ecosystem: "pip"
|
||||
- package-ecosystem: "uv"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
|
||||
25
.github/workflows/build-docs.yml
vendored
25
.github/workflows/build-docs.yml
vendored
@@ -8,9 +8,6 @@ on:
|
||||
- opened
|
||||
- synchronize
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -31,8 +28,8 @@ jobs:
|
||||
- README.md
|
||||
- docs/**
|
||||
- docs_src/**
|
||||
- requirements-docs.txt
|
||||
- pyproject.toml
|
||||
- uv.lock
|
||||
- mkdocs.yml
|
||||
- mkdocs.env.yml
|
||||
- .github/workflows/build-docs.yml
|
||||
@@ -49,21 +46,20 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install docs extras
|
||||
run: uv pip install -r requirements-docs.txt
|
||||
run: uv sync --locked --no-dev --group docs
|
||||
- name: Export Language Codes
|
||||
id: show-langs
|
||||
run: |
|
||||
echo "langs=$(python ./scripts/docs.py langs-json)" >> $GITHUB_OUTPUT
|
||||
echo "langs=$(uv run ./scripts/docs.py langs-json)" >> $GITHUB_OUTPUT
|
||||
|
||||
build-docs:
|
||||
needs:
|
||||
@@ -83,25 +79,24 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install docs extras
|
||||
run: uv pip install -r requirements-docs.txt
|
||||
run: uv sync --locked --no-dev --group docs
|
||||
- name: Update Languages
|
||||
run: python ./scripts/docs.py update-languages
|
||||
run: uv run ./scripts/docs.py update-languages
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: mkdocs-cards-${{ matrix.lang }}-${{ github.ref }}
|
||||
path: docs/${{ matrix.lang }}/.cache
|
||||
- name: Build Docs
|
||||
run: python ./scripts/docs.py build-lang ${{ matrix.lang }}
|
||||
run: uv run ./scripts/docs.py build-lang ${{ matrix.lang }}
|
||||
- uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: docs-site-${{ matrix.lang }}
|
||||
|
||||
12
.github/workflows/contributors.yml
vendored
12
.github/workflows/contributors.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
job:
|
||||
if: github.repository_owner == 'fastapi'
|
||||
@@ -28,17 +25,16 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
@@ -48,6 +44,6 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }}
|
||||
- name: FastAPI People Contributors
|
||||
run: python ./scripts/contributors.py
|
||||
run: uv run ./scripts/contributors.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }}
|
||||
|
||||
16
.github/workflows/deploy-docs.yml
vendored
16
.github/workflows/deploy-docs.yml
vendored
@@ -12,9 +12,6 @@ permissions:
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
deploy-docs:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -27,19 +24,18 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install GitHub Actions dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
- name: Deploy Docs Status Pending
|
||||
run: python ./scripts/deploy_docs_status.py
|
||||
run: uv run ./scripts/deploy_docs_status.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||
@@ -70,14 +66,14 @@ jobs:
|
||||
command: pages deploy ./site --project-name=${{ env.PROJECT_NAME }} --branch=${{ env.BRANCH }}
|
||||
- name: Deploy Docs Status Error
|
||||
if: failure()
|
||||
run: python ./scripts/deploy_docs_status.py
|
||||
run: uv run ./scripts/deploy_docs_status.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
STATE: "error"
|
||||
- name: Comment Deploy
|
||||
run: python ./scripts/deploy_docs_status.py
|
||||
run: uv run ./scripts/deploy_docs_status.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DEPLOY_URL: ${{ steps.deploy.outputs.deployment-url }}
|
||||
|
||||
12
.github/workflows/label-approved.yml
vendored
12
.github/workflows/label-approved.yml
vendored
@@ -8,9 +8,6 @@ on:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
label-approved:
|
||||
if: github.repository_owner == 'fastapi'
|
||||
@@ -24,19 +21,18 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install GitHub Actions dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
- name: Label Approved
|
||||
run: python ./scripts/label_approved.py
|
||||
run: uv run ./scripts/label_approved.py
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CONFIG: >
|
||||
|
||||
12
.github/workflows/notify-translations.yml
vendored
12
.github/workflows/notify-translations.yml
vendored
@@ -15,9 +15,6 @@ on:
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
job:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -32,17 +29,16 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
@@ -52,7 +48,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Notify Translations
|
||||
run: python ./scripts/notify_translations.py
|
||||
run: uv run ./scripts/notify_translations.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NUMBER: ${{ github.event.inputs.number || null }}
|
||||
|
||||
12
.github/workflows/people.yml
vendored
12
.github/workflows/people.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
job:
|
||||
if: github.repository_owner == 'fastapi'
|
||||
@@ -28,17 +25,16 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
@@ -48,7 +44,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }}
|
||||
- name: FastAPI People Experts
|
||||
run: python ./scripts/people.py
|
||||
run: uv run ./scripts/people.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }}
|
||||
SLEEP_INTERVAL: ${{ vars.PEOPLE_SLEEP_INTERVAL }}
|
||||
|
||||
7
.github/workflows/pre-commit.yml
vendored
7
.github/workflows/pre-commit.yml
vendored
@@ -40,18 +40,15 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
uv venv
|
||||
uv pip install -r requirements.txt
|
||||
run: uv sync --locked --extra all
|
||||
- name: Run prek - pre-commit
|
||||
id: precommit
|
||||
run: uvx prek run --from-ref origin/${GITHUB_BASE_REF} --to-ref HEAD --show-diff-on-failure
|
||||
|
||||
15
.github/workflows/publish.yml
vendored
15
.github/workflows/publish.yml
vendored
@@ -15,6 +15,7 @@ jobs:
|
||||
- fastapi-slim
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -24,19 +25,15 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version-file: ".python-version"
|
||||
# Issue ref: https://github.com/actions/setup-python/issues/436
|
||||
# cache: "pip"
|
||||
# cache-dependency-path: pyproject.toml
|
||||
- name: Install build dependencies
|
||||
run: pip install build
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
- name: Build distribution
|
||||
run: uv build
|
||||
env:
|
||||
TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }}
|
||||
run: python -m build
|
||||
- name: Publish
|
||||
uses: pypa/gh-action-pypi-publish@v1.13.0
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
run: uv publish
|
||||
|
||||
11
.github/workflows/smokeshow.yml
vendored
11
.github/workflows/smokeshow.yml
vendored
@@ -8,9 +8,6 @@ on:
|
||||
permissions:
|
||||
statuses: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
smokeshow:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -23,14 +20,14 @@ jobs:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.13'
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- run: uv pip install -r requirements-github-actions.txt
|
||||
uv.lock
|
||||
- run: uv sync --locked --no-dev --group github-actions
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: coverage-html
|
||||
@@ -41,7 +38,7 @@ jobs:
|
||||
- name: Upload coverage to Smokeshow
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do
|
||||
if smokeshow upload htmlcov; then
|
||||
if uv run smokeshow upload htmlcov; then
|
||||
echo "Smokeshow upload success!"
|
||||
break
|
||||
fi
|
||||
|
||||
12
.github/workflows/sponsors.yml
vendored
12
.github/workflows/sponsors.yml
vendored
@@ -10,9 +10,6 @@ on:
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
job:
|
||||
if: github.repository_owner == 'fastapi'
|
||||
@@ -28,17 +25,16 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
@@ -46,7 +42,7 @@ jobs:
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
- name: FastAPI People Sponsors
|
||||
run: python ./scripts/sponsors.py
|
||||
run: uv run ./scripts/sponsors.py
|
||||
env:
|
||||
SPONSORS_TOKEN: ${{ secrets.SPONSORS_TOKEN }}
|
||||
PR_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }}
|
||||
|
||||
4
.github/workflows/test-redistribute.yml
vendored
4
.github/workflows/test-redistribute.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version-file: ".python-version"
|
||||
- name: Install build dependencies
|
||||
run: pip install build
|
||||
- name: Build source distribution
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
- name: Install test dependencies
|
||||
run: |
|
||||
cd dist/fastapi*/
|
||||
pip install -r requirements-tests.txt
|
||||
pip install --group tests --editable .[all]
|
||||
env:
|
||||
TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }}
|
||||
- name: Run source distribution tests
|
||||
|
||||
26
.github/workflows/test.yml
vendored
26
.github/workflows/test.yml
vendored
@@ -13,7 +13,7 @@ on:
|
||||
- cron: "0 0 * * 1"
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
UV_NO_SYNC: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -44,6 +44,8 @@ jobs:
|
||||
coverage: coverage
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -57,17 +59,16 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
run: uv sync --locked --no-dev --group tests --extra all
|
||||
- run: mkdir coverage
|
||||
- name: Test
|
||||
if: matrix.codspeed != 'codspeed'
|
||||
run: bash scripts/test.sh
|
||||
run: uv run bash scripts/test.sh
|
||||
env:
|
||||
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
||||
@@ -79,7 +80,7 @@ jobs:
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
||||
with:
|
||||
mode: simulation
|
||||
run: coverage run -m pytest tests/ --codspeed
|
||||
run: uv run coverage run -m pytest tests/ --codspeed
|
||||
# Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow
|
||||
- name: Store coverage files
|
||||
if: matrix.coverage == 'coverage'
|
||||
@@ -100,17 +101,16 @@ jobs:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.11'
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
run: uv sync --locked --no-dev --group tests --extra all
|
||||
- name: Get coverage files
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
@@ -118,15 +118,15 @@ jobs:
|
||||
path: coverage
|
||||
merge-multiple: true
|
||||
- run: ls -la coverage
|
||||
- run: coverage combine coverage
|
||||
- run: coverage html --title "Coverage for ${{ github.sha }}"
|
||||
- run: uv run coverage combine coverage
|
||||
- run: uv run coverage html --title "Coverage for ${{ github.sha }}"
|
||||
- name: Store coverage HTML
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
include-hidden-files: true
|
||||
- run: coverage report --fail-under=100
|
||||
- run: uv run coverage report --fail-under=100
|
||||
|
||||
# https://github.com/marketplace/actions/alls-green#why
|
||||
check: # This job does nothing and is only used for the branch protection
|
||||
|
||||
12
.github/workflows/topic-repos.yml
vendored
12
.github/workflows/topic-repos.yml
vendored
@@ -5,9 +5,6 @@ on:
|
||||
- cron: "0 12 1 * *"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
topic-repos:
|
||||
if: github.repository_owner == 'fastapi'
|
||||
@@ -23,18 +20,17 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install GitHub Actions dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
run: uv sync --locked --no-dev --group github-actions
|
||||
- name: Update Topic Repos
|
||||
run: python ./scripts/topic_repos.py
|
||||
run: uv run ./scripts/topic_repos.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }}
|
||||
|
||||
27
.github/workflows/translate.yml
vendored
27
.github/workflows/translate.yml
vendored
@@ -1,8 +1,8 @@
|
||||
name: Translate
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 5 15 * *" # Run at 05:00 on the 15 of every month
|
||||
# schedule:
|
||||
# - cron: "0 5 15 * *" # Run at 05:00 on the 15 of every month
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -31,9 +31,6 @@ on:
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
langs:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -45,20 +42,20 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt -r requirements-translations.txt
|
||||
run: uv sync --locked --no-dev --group github-actions --group translations
|
||||
- name: Export Language Codes
|
||||
id: show-langs
|
||||
run: |
|
||||
echo "langs=$(python ./scripts/translate.py llm-translatable-json)" >> $GITHUB_OUTPUT
|
||||
echo "commands=$(python ./scripts/translate.py commands-json)" >> $GITHUB_OUTPUT
|
||||
echo "langs=$(uv run ./scripts/translate.py llm-translatable-json)" >> $GITHUB_OUTPUT
|
||||
echo "commands=$(uv run ./scripts/translate.py commands-json)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
LANGUAGE: ${{ github.event.inputs.language }}
|
||||
COMMAND: ${{ github.event.inputs.command }}
|
||||
@@ -84,15 +81,15 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version-file: ".python-version"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt -r requirements-translations.txt
|
||||
run: uv sync --locked --no-dev --group github-actions --group translations
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
@@ -104,8 +101,8 @@ jobs:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
- name: FastAPI Translate
|
||||
run: |
|
||||
python ./scripts/translate.py ${{ matrix.command }}
|
||||
python ./scripts/translate.py make-pr
|
||||
uv run ./scripts/translate.py ${{ matrix.command }}
|
||||
uv run ./scripts/translate.py make-pr
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -29,7 +29,4 @@ archive.zip
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Ignore while the setup still depends on requirements.txt files
|
||||
uv.lock
|
||||
|
||||
.codspeed
|
||||
|
||||
@@ -6,6 +6,7 @@ repos:
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
args: ['--maxkb=750']
|
||||
exclude: ^uv.lock$
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
args:
|
||||
|
||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.11
|
||||
@@ -4,213 +4,197 @@ Translate to German (Deutsch).
|
||||
|
||||
Language code: de.
|
||||
|
||||
|
||||
### Definitions
|
||||
|
||||
"hyphen"
|
||||
The character «-»
|
||||
Unicode U+002D (HYPHEN-MINUS)
|
||||
Alternative names: hyphen, dash, minus sign
|
||||
|
||||
"dash"
|
||||
The character «–»
|
||||
Unicode U+2013 (EN DASH)
|
||||
German name: Halbgeviertstrich
|
||||
|
||||
|
||||
### Grammar to use when talking to the reader
|
||||
|
||||
Use the formal grammar (use «Sie» instead of «Du»).
|
||||
|
||||
Use the formal grammar (use `Sie` instead of `Du`).
|
||||
|
||||
### Quotes
|
||||
|
||||
1) Convert neutral double quotes («"») and English double typographic quotes («“» and «”») to German double typographic quotes («„» and «“»). Convert neutral single quotes («'») and English single typographic quotes («‘» and «’») to German single typographic quotes («‚» and «‘»). Do NOT convert «`"» to «„», do NOT convert «"`» to «“».
|
||||
1) Convert neutral double quotes (`"`) to German double typographic quotes (`„` and `“`). Convert neutral single quotes (`'`) to German single typographic quotes (`‚` and `‘`).
|
||||
|
||||
Do NOT convert quotes in code snippets and code blocks to their German typographic equivalents.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
"Hello world"
|
||||
“Hello Universe”
|
||||
"He said: 'Hello'"
|
||||
“my name is ‘Nils’”
|
||||
`"__main__"`
|
||||
`"items"`
|
||||
»»»
|
||||
```
|
||||
"Hello world"
|
||||
“Hello Universe”
|
||||
"He said: 'Hello'"
|
||||
“my name is ‘Nils’”
|
||||
`"__main__"`
|
||||
`"items"`
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
„Hallo Welt“
|
||||
„Hallo Universum“
|
||||
„Er sagte: ‚Hallo‘“
|
||||
„Mein Name ist ‚Nils‘“
|
||||
`"__main__"`
|
||||
`"items"`
|
||||
»»»
|
||||
Result (German):
|
||||
|
||||
```
|
||||
„Hallo Welt“
|
||||
„Hallo Universum“
|
||||
„Er sagte: ‚Hallo‘“
|
||||
„Mein Name ist ‚Nils‘“
|
||||
`"__main__"`
|
||||
`"items"`
|
||||
```
|
||||
|
||||
### Ellipsis
|
||||
|
||||
1) Make sure there is a space between an ellipsis and a word following or preceding the ellipsis.
|
||||
- Make sure there is a space between an ellipsis and a word following or preceding the ellipsis.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
...as we intended.
|
||||
...this would work:
|
||||
...etc.
|
||||
others...
|
||||
More to come...
|
||||
»»»
|
||||
```
|
||||
...as we intended.
|
||||
...this would work:
|
||||
...etc.
|
||||
others...
|
||||
More to come...
|
||||
```
|
||||
|
||||
Result (German):
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
... wie wir es beabsichtigt hatten.
|
||||
... das würde funktionieren:
|
||||
... usw.
|
||||
Andere ...
|
||||
Später mehr ...
|
||||
»»»
|
||||
|
||||
2) This does not apply in URLs, code blocks, and code snippets. Do not remove or add spaces there.
|
||||
```
|
||||
... wie wir es beabsichtigt hatten.
|
||||
... das würde funktionieren:
|
||||
... usw.
|
||||
Andere ...
|
||||
Später mehr ...
|
||||
```
|
||||
|
||||
- This does not apply in URLs, code blocks, and code snippets. Do not remove or add spaces there.
|
||||
|
||||
### Headings
|
||||
|
||||
1) Translate headings using the infinite form.
|
||||
- Translate headings using the infinite form.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
## Create a Project { #create-a-project }
|
||||
»»»
|
||||
```
|
||||
## Create a Project { #create-a-project }
|
||||
```
|
||||
|
||||
Translate with (German):
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
## Ein Projekt erstellen { #create-a-project }
|
||||
»»»
|
||||
```
|
||||
## Ein Projekt erstellen { #create-a-project }
|
||||
```
|
||||
|
||||
Do NOT translate with (German):
|
||||
Do NOT translate with (German):
|
||||
|
||||
«««
|
||||
## Erstellen Sie ein Projekt { #create-a-project }
|
||||
»»»
|
||||
```
|
||||
## Erstellen Sie ein Projekt { #create-a-project }
|
||||
```
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
# Install Packages { #install-packages }
|
||||
»»»
|
||||
```
|
||||
# Install Packages { #install-packages }
|
||||
```
|
||||
|
||||
Translate with (German):
|
||||
Translate with (German):
|
||||
|
||||
«««
|
||||
# Pakete installieren { #install-packages }
|
||||
»»»
|
||||
```
|
||||
# Pakete installieren { #install-packages }
|
||||
```
|
||||
|
||||
Do NOT translate with (German):
|
||||
Do NOT translate with (German):
|
||||
|
||||
«««
|
||||
# Installieren Sie Pakete { #install-packages }
|
||||
»»»
|
||||
```
|
||||
# Installieren Sie Pakete { #install-packages }
|
||||
```
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
### Run Your Program { #run-your-program }
|
||||
»»»
|
||||
```
|
||||
### Run Your Program { #run-your-program }
|
||||
```
|
||||
|
||||
Translate with (German):
|
||||
Translate with (German):
|
||||
|
||||
«««
|
||||
### Ihr Programm ausführen { #run-your-program }
|
||||
»»»
|
||||
```
|
||||
### Ihr Programm ausführen { #run-your-program }
|
||||
```
|
||||
|
||||
Do NOT translate with (German):
|
||||
Do NOT translate with (German):
|
||||
|
||||
«««
|
||||
### Führen Sie Ihr Programm aus { #run-your-program }
|
||||
»»»
|
||||
```
|
||||
### Führen Sie Ihr Programm aus { #run-your-program }
|
||||
```
|
||||
|
||||
2) Make sure that the translated part of the heading does not end with a period.
|
||||
- Make sure that the translated part of the heading does not end with a period.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
## Another module with `APIRouter` { #another-module-with-apirouter }
|
||||
»»»
|
||||
```
|
||||
## Another module with `APIRouter` { #another-module-with-apirouter }
|
||||
```
|
||||
|
||||
Translate with (German):
|
||||
Translate with (German):
|
||||
|
||||
«««
|
||||
## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter }
|
||||
»»»
|
||||
```
|
||||
## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter }
|
||||
```
|
||||
|
||||
Do NOT translate with (German) – notice the added period:
|
||||
Do NOT translate with (German) – notice the added period:
|
||||
|
||||
«««
|
||||
## Ein weiteres Modul mit `APIRouter`. { #another-module-with-apirouter }
|
||||
»»»
|
||||
```
|
||||
## Ein weiteres Modul mit `APIRouter`. { #another-module-with-apirouter }
|
||||
```
|
||||
|
||||
3) Replace occurrences of literal « - » (a space followed by a hyphen followed by a space) with « – » (a space followed by a dash followed by a space) in the translated part of the heading.
|
||||
- Replace occurrences of literal ` - ` (a space followed by a hyphen followed by a space) with ` – ` (a space followed by a dash followed by a space) in the translated part of the heading.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
# FastAPI in Containers - Docker { #fastapi-in-containers-docker }
|
||||
»»»
|
||||
```
|
||||
# FastAPI in Containers - Docker { #fastapi-in-containers-docker }
|
||||
```
|
||||
|
||||
Translate with (German) – notice the dash:
|
||||
Translate with (German) – notice the dash:
|
||||
|
||||
«««
|
||||
# FastAPI in Containern – Docker { #fastapi-in-containers-docker }
|
||||
»»»
|
||||
```
|
||||
# FastAPI in Containern – Docker { #fastapi-in-containers-docker }
|
||||
```
|
||||
|
||||
Do NOT translate with (German) – notice the hyphen:
|
||||
Do NOT translate with (German) – notice the hyphen:
|
||||
|
||||
«««
|
||||
# FastAPI in Containern - Docker { #fastapi-in-containers-docker }
|
||||
»»»
|
||||
```
|
||||
# FastAPI in Containern - Docker { #fastapi-in-containers-docker }
|
||||
```
|
||||
|
||||
3.1) Do not apply rule 3 when there is no space before or no space after the hyphen.
|
||||
- Do not apply rule 3 when there is no space before or no space after the hyphen.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
## Type hints and annotations { #type-hints-and-annotations }
|
||||
»»»
|
||||
```
|
||||
## Type hints and annotations { #type-hints-and-annotations }
|
||||
```
|
||||
|
||||
Translate with (German) – notice the hyphen:
|
||||
Translate with (German) - notice the hyphen:
|
||||
|
||||
«««
|
||||
## Typhinweise und -annotationen { #type-hints-and-annotations }
|
||||
»»»
|
||||
```
|
||||
## Typhinweise und -annotationen { #type-hints-and-annotations }
|
||||
```
|
||||
|
||||
Do NOT translate with (German) – notice the dash:
|
||||
Do NOT translate with (German) - notice the dash:
|
||||
|
||||
«««
|
||||
## Typhinweise und –annotationen { #type-hints-and-annotations }
|
||||
»»»
|
||||
```
|
||||
## Typhinweise und –annotationen { #type-hints-and-annotations }
|
||||
```
|
||||
|
||||
3.2) Do not apply rule 3 to the untranslated part of the heading inside curly brackets, which you shall not translate.
|
||||
- Do not modify the hyphens in the content in headers inside of curly braces, which you shall not translate.
|
||||
|
||||
|
||||
### German instructions, when to use and when not to use hyphens in words (written in first person, which is you)
|
||||
### German instructions, when to use and when not to use hyphens in words (written in first person, which is you).
|
||||
|
||||
In der Regel versuche ich so weit wie möglich Worte zusammenzuschreiben, also ohne Bindestrich, es sei denn, es ist Konkretesding-Klassevondingen, etwa «Pydantic-Modell» (aber: «Datenbankmodell»), «Python-Modul» (aber: «Standardmodul»). Ich setze auch einen Bindestrich, wenn er die gleichen Buchstaben verbindet, etwa «Enum-Member», «Cloud-Dienst», «Template-Engine». Oder wenn das Wort sonst einfach zu lang wird, etwa, «Performance-Optimierung». Oder um etwas visuell besser zu dokumentieren, etwa «Pfadoperation-Dekorator», «Pfadoperation-Funktion».
|
||||
|
||||
@@ -219,123 +203,122 @@ In der Regel versuche ich so weit wie möglich Worte zusammenzuschreiben, also o
|
||||
|
||||
Ich versuche nicht, alles einzudeutschen. Das bezieht sich besonders auf Begriffe aus dem Bereich der Programmierung. Ich wandele zwar korrekt in Großschreibung um und setze Bindestriche, wo notwendig, aber ansonsten lasse ich solch ein Wort unverändert. Beispielsweise wird aus dem englischen Wort «string» in der deutschen Übersetzung «String», aber nicht «Zeichenkette». Oder aus dem englischen Wort «request body» wird in der deutschen Übersetzung «Requestbody», aber nicht «Anfragekörper». Oder aus dem englischen «response» wird im Deutschen «Response», aber nicht «Antwort».
|
||||
|
||||
|
||||
### List of English terms and their preferred German translations
|
||||
|
||||
Below is a list of English terms and their preferred German translations, separated by a colon («:»). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. In the below list, a term or a translation may be followed by an explanation in brackets, which explains when to translate the term this way. If a translation is preceded by «NOT», then that means: do NOT use this translation for this term. English nouns, starting with the word «the», have the German genus – «der», «die», «das» – prepended to their German translation, to help you to grammatically decline them in the translation. They are given in singular case, unless they have «(plural)» attached, which means they are given in plural case. Verbs are given in the full infinitive – starting with the word «to».
|
||||
Below is a list of English terms and their preferred German translations, separated by a colon (:). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. In the below list, a term or a translation may be followed by an explanation in brackets, which explains when to translate the term this way. If a translation is preceded by `NOT`, then that means: do NOT use this translation for this term. English nouns, starting with the word `the`, have the German genus – `der`, `die`, `das` – prepended to their German translation, to help you to grammatically decline them in the translation. They are given in singular case, unless they have `(plural)` attached, which means they are given in plural case. Verbs are given in the full infinitive – starting with the word `to`.
|
||||
|
||||
* «/// check»: «/// check | Testen»
|
||||
* «/// danger»: «/// danger | Gefahr»
|
||||
* «/// info»: «/// info | Info»
|
||||
* «/// note | Technical Details»: «/// note | Technische Details»
|
||||
* «/// note»: «/// note | Hinweis»
|
||||
* «/// tip»: «/// tip | Tipp»
|
||||
* «/// warning»: «/// warning | Achtung»
|
||||
* «you»: «Sie»
|
||||
* «your»: «Ihr»
|
||||
* «e.g»: «z. B.»
|
||||
* «etc.»: «usw.»
|
||||
* «ref»: «Ref.»
|
||||
* «the Tutorial - User guide»: «das Tutorial – Benutzerhandbuch»
|
||||
* «the Advanced User Guide»: «das Handbuch für fortgeschrittene Benutzer»
|
||||
* «the SQLModel docs»: «die SQLModel-Dokumentation»
|
||||
* «the docs»: «die Dokumentation» (use singular case)
|
||||
* «the env var»: «die Umgebungsvariable»
|
||||
* «the `PATH` environment variable»: «die `PATH`-Umgebungsvariable»
|
||||
* «the `PATH`»: «der `PATH`»
|
||||
* «the `requirements.txt`»: «die `requirements.txt`»
|
||||
* «the API Router»: «der API-Router»
|
||||
* «the Authorization-Header»: «der Autorisierungsheader»
|
||||
* «the `Authorization`-Header»: «der `Authorization`-Header»
|
||||
* «the background task»: «der Hintergrundtask»
|
||||
* «the button»: «der Button»
|
||||
* «the cloud provider»: «der Cloudanbieter»
|
||||
* «the CLI»: «Das CLI»
|
||||
* «the coverage»: «Die Testabdeckung»
|
||||
* «the command line interface»: «Das Kommandozeileninterface»
|
||||
* «the default value»: «der Defaultwert»
|
||||
* «the default value»: NOT «der Standardwert»
|
||||
* «the default declaration»: «die Default-Deklaration»
|
||||
* «the deployment»: «das Deployment»
|
||||
* «the dict»: «das Dict»
|
||||
* «the dictionary»: «das Dictionary»
|
||||
* «the enumeration»: «die Enumeration»
|
||||
* «the enum»: «das Enum»
|
||||
* «the engine»: «die Engine»
|
||||
* «the error response»: «die Error-Response»
|
||||
* «the event»: «das Event»
|
||||
* «the exception»: «die Exception»
|
||||
* «the exception handler»: «der Exceptionhandler»
|
||||
* «the form model»: «das Formularmodell»
|
||||
* «the form body»: «der Formularbody»
|
||||
* «the header»: «der Header»
|
||||
* «the headers» (plural): «die Header»
|
||||
* «in headers» (plural): «in Headern»
|
||||
* «the forwarded header»: «der Forwarded-Header»
|
||||
* «the lifespan event»: «das Lifespan-Event»
|
||||
* «the lock»: «der Lock»
|
||||
* «the locking»: «das Locking»
|
||||
* «the mobile application»: «die Mobile-Anwendung»
|
||||
* «the model object»: «das Modellobjekt»
|
||||
* «the mounting»: «das Mounten»
|
||||
* «mounted»: «gemountet»
|
||||
* «the origin»: «das Origin»
|
||||
* «the override»: «Die Überschreibung»
|
||||
* «the parameter»: «der Parameter»
|
||||
* «the parameters» (plural): «die Parameter»
|
||||
* «the function parameter»: «der Funktionsparameter»
|
||||
* «the default parameter»: «der Defaultparameter»
|
||||
* «the body parameter»: «der Body-Parameter»
|
||||
* «the request body parameter»: «der Requestbody-Parameter»
|
||||
* «the path parameter»: «der Pfad-Parameter»
|
||||
* «the query parameter»: «der Query-Parameter»
|
||||
* «the cookie parameter»: «der Cookie-Parameter»
|
||||
* «the header parameter»: «der Header-Parameter»
|
||||
* «the form parameter»: «der Formular-Parameter»
|
||||
* «the payload»: «die Payload»
|
||||
* «the performance»: NOT «die Performance»
|
||||
* «the query»: «die Query»
|
||||
* «the recap»: «die Zusammenfassung»
|
||||
* «the request» (what the client sends to the server): «der Request»
|
||||
* «the request body»: «der Requestbody»
|
||||
* «the request bodies» (plural): «die Requestbodys»
|
||||
* «the response» (what the server sends back to the client): «die Response»
|
||||
* «the return type»: «der Rückgabetyp»
|
||||
* «the return value»: «der Rückgabewert»
|
||||
* «the startup» (the event of the app): «der Startup»
|
||||
* «the shutdown» (the event of the app): «der Shutdown»
|
||||
* «the startup event»: «das Startup-Event»
|
||||
* «the shutdown event»: «das Shutdown-Event»
|
||||
* «the startup» (of the server): «das Hochfahren»
|
||||
* «the startup» (the company): «das Startup»
|
||||
* «the SDK»: «das SDK»
|
||||
* «the tag»: «der Tag»
|
||||
* «the type annotation»: «die Typannotation»
|
||||
* «the type hint»: «der Typhinweis»
|
||||
* «the wildcard»: «die Wildcard»
|
||||
* «the worker class»: «die Workerklasse»
|
||||
* «the worker class»: NOT «die Arbeiterklasse»
|
||||
* «the worker process»: «der Workerprozess»
|
||||
* «the worker process»: NOT «der Arbeiterprozess»
|
||||
* «to commit»: «committen»
|
||||
* «to deploy» (in the cloud): «deployen»
|
||||
* «to modify»: «ändern»
|
||||
* «to serve» (an application): «bereitstellen»
|
||||
* «to serve» (a response): «ausliefern»
|
||||
* «to serve»: NOT «bedienen»
|
||||
* «to upgrade»: «aktualisieren»
|
||||
* «to wrap»: «wrappen»
|
||||
* «to wrap»: NOT «hüllen»
|
||||
* «`foo` as a `type`»: «`foo` vom Typ `type`»
|
||||
* «`foo` as a `type`»: «`foo`, ein `type`»
|
||||
* «FastAPI's X»: «FastAPIs X»
|
||||
* «Starlette's Y»: «Starlettes Y»
|
||||
* «X is case-sensitive»: «Groß-/Kleinschreibung ist relevant in X»
|
||||
* «X is case-insensitive»: «Groß-/Kleinschreibung ist nicht relevant in X»
|
||||
* «standard Python»: «Standard-Python»
|
||||
* «deprecated»: «deprecatet»
|
||||
* /// check: /// check | Testen
|
||||
* /// danger: /// danger | Gefahr
|
||||
* /// info: /// info | Info
|
||||
* /// note | Technical Details: /// note | Technische Details
|
||||
* /// note: /// note | Hinweis
|
||||
* /// tip: /// tip | Tipp
|
||||
* /// warning: /// warning | Achtung
|
||||
* you: Sie
|
||||
* your: Ihr
|
||||
* e.g: z. B.
|
||||
* etc.: usw.
|
||||
* ref: Ref.
|
||||
* the Tutorial - User guide: das Tutorial – Benutzerhandbuch
|
||||
* the Advanced User Guide: das Handbuch für fortgeschrittene Benutzer
|
||||
* the SQLModel docs: die SQLModel-Dokumentation
|
||||
* the docs: die Dokumentation (use singular case)
|
||||
* the env var: die Umgebungsvariable
|
||||
* the `PATH` environment variable: die `PATH`-Umgebungsvariable
|
||||
* the `PATH`: der `PATH`
|
||||
* the `requirements.txt`: die `requirements.txt`
|
||||
* the API Router: der API-Router
|
||||
* the Authorization-Header: der Autorisierungsheader
|
||||
* the `Authorization`-Header: der `Authorization`-Header
|
||||
* the background task: der Hintergrundtask
|
||||
* the button: der Button
|
||||
* the cloud provider: der Cloudanbieter
|
||||
* the CLI: Das CLI
|
||||
* the coverage: Die Testabdeckung
|
||||
* the command line interface: Das Kommandozeileninterface
|
||||
* the default value: der Defaultwert
|
||||
* the default value: NOT der Standardwert
|
||||
* the default declaration: die Default-Deklaration
|
||||
* the deployment: das Deployment
|
||||
* the dict: das Dict
|
||||
* the dictionary: das Dictionary
|
||||
* the enumeration: die Enumeration
|
||||
* the enum: das Enum
|
||||
* the engine: die Engine
|
||||
* the error response: die Error-Response
|
||||
* the event: das Event
|
||||
* the exception: die Exception
|
||||
* the exception handler: der Exceptionhandler
|
||||
* the form model: das Formularmodell
|
||||
* the form body: der Formularbody
|
||||
* the header: der Header
|
||||
* the headers (plural): die Header
|
||||
* in headers (plural): in Headern
|
||||
* the forwarded header: der Forwarded-Header
|
||||
* the lifespan event: das Lifespan-Event
|
||||
* the lock: der Lock
|
||||
* the locking: das Locking
|
||||
* the mobile application: die Mobile-Anwendung
|
||||
* the model object: das Modellobjekt
|
||||
* the mounting: das Mounten
|
||||
* mounted: gemountet
|
||||
* the origin: das Origin
|
||||
* the override: Die Überschreibung
|
||||
* the parameter: der Parameter
|
||||
* the parameters (plural): die Parameter
|
||||
* the function parameter: der Funktionsparameter
|
||||
* the default parameter: der Defaultparameter
|
||||
* the body parameter: der Body-Parameter
|
||||
* the request body parameter: der Requestbody-Parameter
|
||||
* the path parameter: der Pfad-Parameter
|
||||
* the query parameter: der Query-Parameter
|
||||
* the cookie parameter: der Cookie-Parameter
|
||||
* the header parameter: der Header-Parameter
|
||||
* the form parameter: der Formular-Parameter
|
||||
* the payload: die Payload
|
||||
* the performance: NOT die Performance
|
||||
* the query: die Query
|
||||
* the recap: die Zusammenfassung
|
||||
* the request (what the client sends to the server): der Request
|
||||
* the request body: der Requestbody
|
||||
* the request bodies (plural): die Requestbodys
|
||||
* the response (what the server sends back to the client): die Response
|
||||
* the return type: der Rückgabetyp
|
||||
* the return value: der Rückgabewert
|
||||
* the startup (the event of the app): der Startup
|
||||
* the shutdown (the event of the app): der Shutdown
|
||||
* the startup event: das Startup-Event
|
||||
* the shutdown event: das Shutdown-Event
|
||||
* the startup (of the server): das Hochfahren
|
||||
* the startup (the company): das Startup
|
||||
* the SDK: das SDK
|
||||
* the tag: der Tag
|
||||
* the type annotation: die Typannotation
|
||||
* the type hint: der Typhinweis
|
||||
* the wildcard: die Wildcard
|
||||
* the worker class: die Workerklasse
|
||||
* the worker class: NOT die Arbeiterklasse
|
||||
* the worker process: der Workerprozess
|
||||
* the worker process: NOT der Arbeiterprozess
|
||||
* to commit: committen
|
||||
* to deploy (in the cloud): deployen
|
||||
* to modify: ändern
|
||||
* to serve (an application): bereitstellen
|
||||
* to serve (a response): ausliefern
|
||||
* to serve: NOT bedienen
|
||||
* to upgrade: aktualisieren
|
||||
* to wrap: wrappen
|
||||
* to wrap: NOT hüllen
|
||||
* `foo` as a `type`: `foo` vom Typ `type`
|
||||
* `foo` as a `type`: `foo`, ein `type`
|
||||
* FastAPI's X: FastAPIs X
|
||||
* Starlette's Y: Starlettes Y
|
||||
* X is case-sensitive: Groß-/Kleinschreibung ist relevant in X
|
||||
* X is case-insensitive: Groß-/Kleinschreibung ist nicht relevant in X
|
||||
* standard Python: Standard-Python
|
||||
* deprecated: deprecatet
|
||||
|
||||
|
||||
### Other rules
|
||||
|
||||
Preserve indentation. Keep emoticons. Encode in utf-8. Use Linux line breaks (LF).
|
||||
Preserve indentation. Keep emojis. Encode in utf-8. Use Linux line breaks (LF).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 808
|
||||
count: 857
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
dependabot:
|
||||
@@ -10,7 +10,7 @@ dependabot:
|
||||
url: https://github.com/apps/dependabot
|
||||
alejsdev:
|
||||
login: alejsdev
|
||||
count: 52
|
||||
count: 53
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
pre-commit-ci:
|
||||
@@ -18,6 +18,11 @@ pre-commit-ci:
|
||||
count: 50
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
|
||||
url: https://github.com/apps/pre-commit-ci
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 36
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
github-actions:
|
||||
login: github-actions
|
||||
count: 26
|
||||
@@ -28,26 +33,21 @@ Kludex:
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
|
||||
url: https://github.com/Kludex
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
dmontagu:
|
||||
login: dmontagu
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
url: https://github.com/dmontagu
|
||||
svlandeg:
|
||||
login: svlandeg
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
|
||||
url: https://github.com/svlandeg
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
svlandeg:
|
||||
login: svlandeg
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
|
||||
url: https://github.com/svlandeg
|
||||
euri10:
|
||||
login: euri10
|
||||
count: 13
|
||||
@@ -553,6 +553,11 @@ DanielKusyDev:
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36250676?u=2ea6114ff751fc48b55f231987a0e2582c6b1bd2&v=4
|
||||
url: https://github.com/DanielKusyDev
|
||||
Viicos:
|
||||
login: Viicos
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4
|
||||
url: https://github.com/Viicos
|
||||
DanielYang59:
|
||||
login: DanielYang59
|
||||
count: 2
|
||||
|
||||
@@ -2,57 +2,51 @@ sponsors:
|
||||
- - login: renderinc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4
|
||||
url: https://github.com/renderinc
|
||||
- login: andrew-propelauth
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4
|
||||
url: https://github.com/andrew-propelauth
|
||||
- login: blockbee-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4
|
||||
url: https://github.com/blockbee-io
|
||||
- login: zuplo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85497839?v=4
|
||||
url: https://github.com/zuplo
|
||||
- login: coderabbitai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4
|
||||
url: https://github.com/coderabbitai
|
||||
- login: greptileai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4
|
||||
url: https://github.com/greptileai
|
||||
- login: subtotal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4
|
||||
url: https://github.com/subtotal
|
||||
- login: greptileai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4
|
||||
url: https://github.com/greptileai
|
||||
- login: coderabbitai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4
|
||||
url: https://github.com/coderabbitai
|
||||
- login: zuplo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85497839?v=4
|
||||
url: https://github.com/zuplo
|
||||
- login: blockbee-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4
|
||||
url: https://github.com/blockbee-io
|
||||
- login: andrew-propelauth
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4
|
||||
url: https://github.com/andrew-propelauth
|
||||
- login: railwayapp
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4
|
||||
url: https://github.com/railwayapp
|
||||
- - login: dribia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4
|
||||
url: https://github.com/dribia
|
||||
- login: svix
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
|
||||
url: https://github.com/svix
|
||||
- - login: speakeasy-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4
|
||||
url: https://github.com/speakeasy-api
|
||||
- login: stainless-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/88061651?v=4
|
||||
url: https://github.com/stainless-api
|
||||
- login: speakeasy-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4
|
||||
url: https://github.com/speakeasy-api
|
||||
- login: databento
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4
|
||||
url: https://github.com/databento
|
||||
- login: svix
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
|
||||
url: https://github.com/svix
|
||||
- login: permitio
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4
|
||||
url: https://github.com/permitio
|
||||
- - login: Ponte-Energy-Partners
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4
|
||||
url: https://github.com/Ponte-Energy-Partners
|
||||
- login: LambdaTest-Inc
|
||||
- login: databento
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4
|
||||
url: https://github.com/databento
|
||||
- - login: LambdaTest-Inc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4
|
||||
url: https://github.com/LambdaTest-Inc
|
||||
- login: Ponte-Energy-Partners
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4
|
||||
url: https://github.com/Ponte-Energy-Partners
|
||||
- login: BoostryJP
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
|
||||
url: https://github.com/BoostryJP
|
||||
- login: requestly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12287519?v=4
|
||||
url: https://github.com/requestly
|
||||
- login: acsone
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4
|
||||
url: https://github.com/acsone
|
||||
@@ -68,9 +62,6 @@ sponsors:
|
||||
- login: Doist
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
|
||||
url: https://github.com/Doist
|
||||
- login: bholagabbar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11693595?v=4
|
||||
url: https://github.com/bholagabbar
|
||||
- - login: mainframeindustries
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
||||
url: https://github.com/mainframeindustries
|
||||
@@ -86,6 +77,9 @@ sponsors:
|
||||
- login: ChargeStorm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4
|
||||
url: https://github.com/ChargeStorm
|
||||
- login: ibrahimpelumi6142
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113442282?v=4
|
||||
url: https://github.com/ibrahimpelumi6142
|
||||
- login: nilslindemann
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
@@ -116,124 +110,127 @@ sponsors:
|
||||
- login: Leay15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||
url: https://github.com/Leay15
|
||||
- login: Karine-Bauch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4
|
||||
url: https://github.com/Karine-Bauch
|
||||
- login: jugeeem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4
|
||||
url: https://github.com/jugeeem
|
||||
- login: patsatsia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
|
||||
url: https://github.com/patsatsia
|
||||
- login: anthonycepeda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: patricioperezv
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4
|
||||
url: https://github.com/patricioperezv
|
||||
- login: chickenandstats
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
|
||||
url: https://github.com/chickenandstats
|
||||
- login: Karine-Bauch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4
|
||||
url: https://github.com/Karine-Bauch
|
||||
- login: kaoru0310
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
|
||||
url: https://github.com/kaoru0310
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: knallgelb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
|
||||
url: https://github.com/knallgelb
|
||||
- login: dblackrun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
|
||||
url: https://github.com/dblackrun
|
||||
- login: zsinx6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||
url: https://github.com/zsinx6
|
||||
- login: kennywakeland
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3631417?u=7c8f743f1ae325dfadea7c62bbf1abd6a824fc55&v=4
|
||||
url: https://github.com/kennywakeland
|
||||
- login: aacayaco
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
|
||||
url: https://github.com/aacayaco
|
||||
- login: anomaly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||
url: https://github.com/anomaly
|
||||
- login: mj0331
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4
|
||||
url: https://github.com/mj0331
|
||||
- login: gorhack
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
|
||||
url: https://github.com/gorhack
|
||||
- login: Ryandaydev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
- login: chickenandstats
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
|
||||
url: https://github.com/chickenandstats
|
||||
- login: patricioperezv
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4
|
||||
url: https://github.com/patricioperezv
|
||||
- login: anthonycepeda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: AalbatrossGuy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/68378354?u=0bdeea9356d24f638244131f6d8d1e2d2f3601ca&v=4
|
||||
url: https://github.com/AalbatrossGuy
|
||||
- login: patsatsia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
|
||||
url: https://github.com/patsatsia
|
||||
- login: oliverxchen
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
|
||||
url: https://github.com/oliverxchen
|
||||
- login: paulcwatts
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/150269?u=1819e145d573b44f0ad74b87206d21cd60331d4e&v=4
|
||||
url: https://github.com/paulcwatts
|
||||
- login: robintw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/296686?v=4
|
||||
url: https://github.com/robintw
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
- login: wshayes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: koxudaxi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||
url: https://github.com/koxudaxi
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: mintuhouse
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
|
||||
url: https://github.com/mintuhouse
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
- login: Ryandaydev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: gorhack
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
|
||||
url: https://github.com/gorhack
|
||||
- login: mj0331
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4
|
||||
url: https://github.com/mj0331
|
||||
- login: anomaly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||
url: https://github.com/anomaly
|
||||
- login: aacayaco
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
|
||||
url: https://github.com/aacayaco
|
||||
- login: kennywakeland
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3631417?u=7c8f743f1ae325dfadea7c62bbf1abd6a824fc55&v=4
|
||||
url: https://github.com/kennywakeland
|
||||
- login: zsinx6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||
url: https://github.com/zsinx6
|
||||
- login: dblackrun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
|
||||
url: https://github.com/dblackrun
|
||||
- login: knallgelb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
|
||||
url: https://github.com/knallgelb
|
||||
- login: dodo5522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
|
||||
url: https://github.com/dodo5522
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: jsoques
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
|
||||
url: https://github.com/jsoques
|
||||
- login: dannywade
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
|
||||
url: https://github.com/dannywade
|
||||
- login: khadrawy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
|
||||
url: https://github.com/khadrawy
|
||||
- login: mjohnsey
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
|
||||
url: https://github.com/mjohnsey
|
||||
- login: ashi-agrawal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4
|
||||
url: https://github.com/ashi-agrawal
|
||||
- login: mintuhouse
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
|
||||
url: https://github.com/mintuhouse
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: koxudaxi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||
url: https://github.com/koxudaxi
|
||||
- login: wshayes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
- login: robintw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/296686?v=4
|
||||
url: https://github.com/robintw
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: RaamEEIL
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4
|
||||
url: https://github.com/RaamEEIL
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4
|
||||
url: https://github.com/ternaus
|
||||
- login: eseglem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4
|
||||
url: https://github.com/eseglem
|
||||
- login: FernandoCelmer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4
|
||||
url: https://github.com/FernandoCelmer
|
||||
- login: Rehket
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
|
||||
url: https://github.com/Rehket
|
||||
- login: ashi-agrawal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4
|
||||
url: https://github.com/ashi-agrawal
|
||||
- login: mjohnsey
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
|
||||
url: https://github.com/mjohnsey
|
||||
- login: khadrawy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
|
||||
url: https://github.com/khadrawy
|
||||
- login: dannywade
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
|
||||
url: https://github.com/dannywade
|
||||
- login: jsoques
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
|
||||
url: https://github.com/jsoques
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: hiancdtrsnm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4
|
||||
url: https://github.com/hiancdtrsnm
|
||||
- - login: manoelpqueiroz
|
||||
- login: Rehket
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
|
||||
url: https://github.com/Rehket
|
||||
- login: FernandoCelmer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4
|
||||
url: https://github.com/FernandoCelmer
|
||||
- login: eseglem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4
|
||||
url: https://github.com/eseglem
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4
|
||||
url: https://github.com/ternaus
|
||||
- - login: Artur-Galstyan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63471891?u=e8691f386037e51a737cc0ba866cd8c89e5cf109&v=4
|
||||
url: https://github.com/Artur-Galstyan
|
||||
- login: manoelpqueiroz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4
|
||||
url: https://github.com/manoelpqueiroz
|
||||
- - login: pawamoy
|
||||
@@ -254,9 +251,12 @@ sponsors:
|
||||
- login: hgalytoby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4
|
||||
url: https://github.com/hgalytoby
|
||||
- login: nisutec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
|
||||
url: https://github.com/nisutec
|
||||
- login: johnl28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
|
||||
url: https://github.com/johnl28
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: hoenie-ams
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4
|
||||
url: https://github.com/hoenie-ams
|
||||
@@ -267,93 +267,87 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
||||
url: https://github.com/engineerjoe440
|
||||
- login: bnkc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=4771ac4e64066f0847d40e5b29910adabd9b2372&v=4
|
||||
url: https://github.com/bnkc
|
||||
- login: petercool
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4
|
||||
url: https://github.com/petercool
|
||||
- login: johnl28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
|
||||
url: https://github.com/johnl28
|
||||
- login: PunRabbit
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4
|
||||
url: https://github.com/PunRabbit
|
||||
- login: PelicanQ
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4
|
||||
url: https://github.com/PelicanQ
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
|
||||
url: https://github.com/WillHogan
|
||||
- login: PunRabbit
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4
|
||||
url: https://github.com/PunRabbit
|
||||
- login: my3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4
|
||||
url: https://github.com/my3
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: ddanier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
|
||||
url: https://github.com/ddanier
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
- login: ceb10n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
- login: tochikuji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
|
||||
url: https://github.com/tochikuji
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
|
||||
url: https://github.com/WillHogan
|
||||
- login: miguelgr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
|
||||
url: https://github.com/miguelgr
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
|
||||
url: https://github.com/xncbf
|
||||
- login: DMantis
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4
|
||||
url: https://github.com/DMantis
|
||||
- login: hard-coders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: mntolia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||
url: https://github.com/mntolia
|
||||
- login: Zuzah
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4
|
||||
url: https://github.com/Zuzah
|
||||
- login: TheR1D
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4
|
||||
url: https://github.com/TheR1D
|
||||
- login: tochikuji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
|
||||
url: https://github.com/tochikuji
|
||||
- login: ceb10n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: ddanier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
|
||||
url: https://github.com/ddanier
|
||||
- login: nisutec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
|
||||
url: https://github.com/nisutec
|
||||
- login: joshuatz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
|
||||
url: https://github.com/joshuatz
|
||||
- login: rangulvers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
|
||||
url: https://github.com/rangulvers
|
||||
- login: sdevkota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4
|
||||
url: https://github.com/sdevkota
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: KentShikama
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
|
||||
url: https://github.com/KentShikama
|
||||
- login: katnoria
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4
|
||||
url: https://github.com/katnoria
|
||||
- login: harsh183
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
|
||||
url: https://github.com/harsh183
|
||||
- login: TheR1D
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4
|
||||
url: https://github.com/TheR1D
|
||||
- login: Zuzah
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4
|
||||
url: https://github.com/Zuzah
|
||||
- login: mntolia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||
url: https://github.com/mntolia
|
||||
- login: hard-coders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: DMantis
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4
|
||||
url: https://github.com/DMantis
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
|
||||
url: https://github.com/xncbf
|
||||
- login: moonape1226
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||
url: https://github.com/moonape1226
|
||||
- - login: andrecorumba
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
|
||||
url: https://github.com/andrecorumba
|
||||
- login: KOZ39
|
||||
- login: harsh183
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
|
||||
url: https://github.com/harsh183
|
||||
- login: katnoria
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4
|
||||
url: https://github.com/katnoria
|
||||
- login: KentShikama
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
|
||||
url: https://github.com/KentShikama
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: sdevkota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4
|
||||
url: https://github.com/sdevkota
|
||||
- login: rangulvers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
|
||||
url: https://github.com/rangulvers
|
||||
- - login: KOZ39
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4
|
||||
url: https://github.com/KOZ39
|
||||
- login: rwxd
|
||||
@@ -365,27 +359,24 @@ sponsors:
|
||||
- login: Olegt0rr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4
|
||||
url: https://github.com/Olegt0rr
|
||||
- login: dinoz0rg
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32940067?u=739cda1eb123a2dd5e1db45c361396f239e23f8b&v=4
|
||||
url: https://github.com/dinoz0rg
|
||||
- login: larsyngvelundin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4
|
||||
url: https://github.com/larsyngvelundin
|
||||
- login: hippoley
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4
|
||||
url: https://github.com/hippoley
|
||||
- login: 4anklee
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144109238?u=a79c0d581b2a3d8f3897e7ef4c012640a6c1eb3a&v=4
|
||||
url: https://github.com/4anklee
|
||||
- login: andrecorumba
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
|
||||
url: https://github.com/andrecorumba
|
||||
- login: CoderDeltaLAN
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4
|
||||
url: https://github.com/CoderDeltaLAN
|
||||
- login: onestn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
|
||||
url: https://github.com/onestn
|
||||
- login: hippoley
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4
|
||||
url: https://github.com/hippoley
|
||||
- login: nayasinghania
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4
|
||||
url: https://github.com/nayasinghania
|
||||
- login: onestn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
|
||||
url: https://github.com/onestn
|
||||
- login: Toothwitch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4
|
||||
url: https://github.com/Toothwitch
|
||||
|
||||
@@ -1,495 +1,495 @@
|
||||
- name: full-stack-fastapi-template
|
||||
html_url: https://github.com/fastapi/full-stack-fastapi-template
|
||||
stars: 39475
|
||||
stars: 40534
|
||||
owner_login: fastapi
|
||||
owner_html_url: https://github.com/fastapi
|
||||
- name: Hello-Python
|
||||
html_url: https://github.com/mouredev/Hello-Python
|
||||
stars: 33090
|
||||
stars: 33839
|
||||
owner_login: mouredev
|
||||
owner_html_url: https://github.com/mouredev
|
||||
- name: serve
|
||||
html_url: https://github.com/jina-ai/serve
|
||||
stars: 21798
|
||||
stars: 21819
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: HivisionIDPhotos
|
||||
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos
|
||||
stars: 20258
|
||||
stars: 20457
|
||||
owner_login: Zeyi-Lin
|
||||
owner_html_url: https://github.com/Zeyi-Lin
|
||||
- name: sqlmodel
|
||||
html_url: https://github.com/fastapi/sqlmodel
|
||||
stars: 17212
|
||||
stars: 17458
|
||||
owner_login: fastapi
|
||||
owner_html_url: https://github.com/fastapi
|
||||
- name: Douyin_TikTok_Download_API
|
||||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
|
||||
stars: 15145
|
||||
owner_login: Evil0ctal
|
||||
owner_html_url: https://github.com/Evil0ctal
|
||||
- name: fastapi-best-practices
|
||||
html_url: https://github.com/zhanymkanov/fastapi-best-practices
|
||||
stars: 14644
|
||||
stars: 15923
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: Douyin_TikTok_Download_API
|
||||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
|
||||
stars: 15763
|
||||
owner_login: Evil0ctal
|
||||
owner_html_url: https://github.com/Evil0ctal
|
||||
- name: machine-learning-zoomcamp
|
||||
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
|
||||
stars: 12320
|
||||
stars: 12477
|
||||
owner_login: DataTalksClub
|
||||
owner_html_url: https://github.com/DataTalksClub
|
||||
- name: fastapi_mcp
|
||||
html_url: https://github.com/tadata-org/fastapi_mcp
|
||||
stars: 11174
|
||||
owner_login: tadata-org
|
||||
owner_html_url: https://github.com/tadata-org
|
||||
- name: SurfSense
|
||||
html_url: https://github.com/MODSetter/SurfSense
|
||||
stars: 10858
|
||||
stars: 12299
|
||||
owner_login: MODSetter
|
||||
owner_html_url: https://github.com/MODSetter
|
||||
- name: fastapi_mcp
|
||||
html_url: https://github.com/tadata-org/fastapi_mcp
|
||||
stars: 11351
|
||||
owner_login: tadata-org
|
||||
owner_html_url: https://github.com/tadata-org
|
||||
- name: awesome-fastapi
|
||||
html_url: https://github.com/mjhea0/awesome-fastapi
|
||||
stars: 10758
|
||||
stars: 10932
|
||||
owner_login: mjhea0
|
||||
owner_html_url: https://github.com/mjhea0
|
||||
- name: XHS-Downloader
|
||||
html_url: https://github.com/JoeanAmier/XHS-Downloader
|
||||
stars: 9313
|
||||
stars: 9696
|
||||
owner_login: JoeanAmier
|
||||
owner_html_url: https://github.com/JoeanAmier
|
||||
- name: FastUI
|
||||
html_url: https://github.com/pydantic/FastUI
|
||||
stars: 8915
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: polar
|
||||
html_url: https://github.com/polarsource/polar
|
||||
stars: 8339
|
||||
stars: 9000
|
||||
owner_login: polarsource
|
||||
owner_html_url: https://github.com/polarsource
|
||||
- name: FastUI
|
||||
html_url: https://github.com/pydantic/FastUI
|
||||
stars: 8938
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: FileCodeBox
|
||||
html_url: https://github.com/vastsa/FileCodeBox
|
||||
stars: 7721
|
||||
stars: 7979
|
||||
owner_login: vastsa
|
||||
owner_html_url: https://github.com/vastsa
|
||||
- name: nonebot2
|
||||
html_url: https://github.com/nonebot/nonebot2
|
||||
stars: 7170
|
||||
stars: 7270
|
||||
owner_login: nonebot
|
||||
owner_html_url: https://github.com/nonebot
|
||||
- name: hatchet
|
||||
html_url: https://github.com/hatchet-dev/hatchet
|
||||
stars: 6253
|
||||
stars: 6422
|
||||
owner_login: hatchet-dev
|
||||
owner_html_url: https://github.com/hatchet-dev
|
||||
- name: fastapi-users
|
||||
html_url: https://github.com/fastapi-users/fastapi-users
|
||||
stars: 5849
|
||||
stars: 5915
|
||||
owner_login: fastapi-users
|
||||
owner_html_url: https://github.com/fastapi-users
|
||||
- name: serge
|
||||
html_url: https://github.com/serge-chat/serge
|
||||
stars: 5756
|
||||
stars: 5751
|
||||
owner_login: serge-chat
|
||||
owner_html_url: https://github.com/serge-chat
|
||||
- name: strawberry
|
||||
html_url: https://github.com/strawberry-graphql/strawberry
|
||||
stars: 4569
|
||||
stars: 4580
|
||||
owner_login: strawberry-graphql
|
||||
owner_html_url: https://github.com/strawberry-graphql
|
||||
- name: chatgpt-web-share
|
||||
html_url: https://github.com/chatpire/chatgpt-web-share
|
||||
stars: 4294
|
||||
owner_login: chatpire
|
||||
owner_html_url: https://github.com/chatpire
|
||||
- name: poem
|
||||
html_url: https://github.com/poem-web/poem
|
||||
stars: 4276
|
||||
stars: 4312
|
||||
owner_login: poem-web
|
||||
owner_html_url: https://github.com/poem-web
|
||||
- name: dynaconf
|
||||
html_url: https://github.com/dynaconf/dynaconf
|
||||
stars: 4202
|
||||
owner_login: dynaconf
|
||||
owner_html_url: https://github.com/dynaconf
|
||||
- name: atrilabs-engine
|
||||
html_url: https://github.com/Atri-Labs/atrilabs-engine
|
||||
stars: 4093
|
||||
owner_login: Atri-Labs
|
||||
owner_html_url: https://github.com/Atri-Labs
|
||||
- name: chatgpt-web-share
|
||||
html_url: https://github.com/chatpire/chatgpt-web-share
|
||||
stars: 4284
|
||||
owner_login: chatpire
|
||||
owner_html_url: https://github.com/chatpire
|
||||
- name: Kokoro-FastAPI
|
||||
html_url: https://github.com/remsky/Kokoro-FastAPI
|
||||
stars: 4019
|
||||
stars: 4241
|
||||
owner_login: remsky
|
||||
owner_html_url: https://github.com/remsky
|
||||
- name: dynaconf
|
||||
html_url: https://github.com/dynaconf/dynaconf
|
||||
stars: 4227
|
||||
owner_login: dynaconf
|
||||
owner_html_url: https://github.com/dynaconf
|
||||
- name: devpush
|
||||
html_url: https://github.com/hunvreus/devpush
|
||||
stars: 4173
|
||||
owner_login: hunvreus
|
||||
owner_html_url: https://github.com/hunvreus
|
||||
- name: atrilabs-engine
|
||||
html_url: https://github.com/Atri-Labs/atrilabs-engine
|
||||
stars: 4091
|
||||
owner_login: Atri-Labs
|
||||
owner_html_url: https://github.com/Atri-Labs
|
||||
- name: logfire
|
||||
html_url: https://github.com/pydantic/logfire
|
||||
stars: 3805
|
||||
stars: 3917
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: Yuxi-Know
|
||||
html_url: https://github.com/xerrors/Yuxi-Know
|
||||
stars: 3825
|
||||
owner_login: xerrors
|
||||
owner_html_url: https://github.com/xerrors
|
||||
- name: LitServe
|
||||
html_url: https://github.com/Lightning-AI/LitServe
|
||||
stars: 3719
|
||||
stars: 3767
|
||||
owner_login: Lightning-AI
|
||||
owner_html_url: https://github.com/Lightning-AI
|
||||
- name: fastapi-admin
|
||||
html_url: https://github.com/fastapi-admin/fastapi-admin
|
||||
stars: 3632
|
||||
owner_login: fastapi-admin
|
||||
owner_html_url: https://github.com/fastapi-admin
|
||||
- name: datamodel-code-generator
|
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator
|
||||
stars: 3609
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: huma
|
||||
html_url: https://github.com/danielgtaylor/huma
|
||||
stars: 3603
|
||||
stars: 3721
|
||||
owner_login: danielgtaylor
|
||||
owner_html_url: https://github.com/danielgtaylor
|
||||
- name: datamodel-code-generator
|
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator
|
||||
stars: 3693
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: fastapi-admin
|
||||
html_url: https://github.com/fastapi-admin/fastapi-admin
|
||||
stars: 3667
|
||||
owner_login: fastapi-admin
|
||||
owner_html_url: https://github.com/fastapi-admin
|
||||
- name: farfalle
|
||||
html_url: https://github.com/rashadphz/farfalle
|
||||
stars: 3490
|
||||
stars: 3495
|
||||
owner_login: rashadphz
|
||||
owner_html_url: https://github.com/rashadphz
|
||||
- name: tracecat
|
||||
html_url: https://github.com/TracecatHQ/tracecat
|
||||
stars: 3379
|
||||
stars: 3425
|
||||
owner_login: TracecatHQ
|
||||
owner_html_url: https://github.com/TracecatHQ
|
||||
- name: opyrator
|
||||
html_url: https://github.com/ml-tooling/opyrator
|
||||
stars: 3135
|
||||
stars: 3136
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: docarray
|
||||
html_url: https://github.com/docarray/docarray
|
||||
stars: 3114
|
||||
stars: 3112
|
||||
owner_login: docarray
|
||||
owner_html_url: https://github.com/docarray
|
||||
- name: devpush
|
||||
html_url: https://github.com/hunvreus/devpush
|
||||
stars: 3097
|
||||
owner_login: hunvreus
|
||||
owner_html_url: https://github.com/hunvreus
|
||||
- name: mcp-context-forge
|
||||
html_url: https://github.com/IBM/mcp-context-forge
|
||||
stars: 3073
|
||||
owner_login: IBM
|
||||
owner_html_url: https://github.com/IBM
|
||||
- name: fastapi-realworld-example-app
|
||||
html_url: https://github.com/nsidnev/fastapi-realworld-example-app
|
||||
stars: 3050
|
||||
stars: 3057
|
||||
owner_login: nsidnev
|
||||
owner_html_url: https://github.com/nsidnev
|
||||
- name: uvicorn-gunicorn-fastapi-docker
|
||||
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
|
||||
stars: 2911
|
||||
stars: 2904
|
||||
owner_login: tiangolo
|
||||
owner_html_url: https://github.com/tiangolo
|
||||
- name: mcp-context-forge
|
||||
html_url: https://github.com/IBM/mcp-context-forge
|
||||
stars: 2899
|
||||
owner_login: IBM
|
||||
owner_html_url: https://github.com/IBM
|
||||
- name: best-of-web-python
|
||||
html_url: https://github.com/ml-tooling/best-of-web-python
|
||||
stars: 2648
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: FastAPI-template
|
||||
html_url: https://github.com/s3rius/FastAPI-template
|
||||
stars: 2637
|
||||
stars: 2691
|
||||
owner_login: s3rius
|
||||
owner_html_url: https://github.com/s3rius
|
||||
- name: best-of-web-python
|
||||
html_url: https://github.com/ml-tooling/best-of-web-python
|
||||
stars: 2666
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: YC-Killer
|
||||
html_url: https://github.com/sahibzada-allahyar/YC-Killer
|
||||
stars: 2599
|
||||
stars: 2612
|
||||
owner_login: sahibzada-allahyar
|
||||
owner_html_url: https://github.com/sahibzada-allahyar
|
||||
- name: fastapi-react
|
||||
html_url: https://github.com/Buuntu/fastapi-react
|
||||
stars: 2569
|
||||
owner_login: Buuntu
|
||||
owner_html_url: https://github.com/Buuntu
|
||||
- name: Yuxi-Know
|
||||
html_url: https://github.com/xerrors/Yuxi-Know
|
||||
stars: 2563
|
||||
owner_login: xerrors
|
||||
owner_html_url: https://github.com/xerrors
|
||||
- name: sqladmin
|
||||
html_url: https://github.com/aminalaee/sqladmin
|
||||
stars: 2558
|
||||
stars: 2600
|
||||
owner_login: aminalaee
|
||||
owner_html_url: https://github.com/aminalaee
|
||||
- name: fastapi-react
|
||||
html_url: https://github.com/Buuntu/fastapi-react
|
||||
stars: 2567
|
||||
owner_login: Buuntu
|
||||
owner_html_url: https://github.com/Buuntu
|
||||
- name: RasaGPT
|
||||
html_url: https://github.com/paulpierre/RasaGPT
|
||||
stars: 2451
|
||||
stars: 2456
|
||||
owner_login: paulpierre
|
||||
owner_html_url: https://github.com/paulpierre
|
||||
- name: supabase-py
|
||||
html_url: https://github.com/supabase/supabase-py
|
||||
stars: 2344
|
||||
stars: 2406
|
||||
owner_login: supabase
|
||||
owner_html_url: https://github.com/supabase
|
||||
- name: nextpy
|
||||
html_url: https://github.com/dot-agent/nextpy
|
||||
stars: 2335
|
||||
stars: 2337
|
||||
owner_login: dot-agent
|
||||
owner_html_url: https://github.com/dot-agent
|
||||
- name: fastapi-utils
|
||||
html_url: https://github.com/fastapiutils/fastapi-utils
|
||||
stars: 2291
|
||||
stars: 2290
|
||||
owner_login: fastapiutils
|
||||
owner_html_url: https://github.com/fastapiutils
|
||||
- name: 30-Days-of-Python
|
||||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
|
||||
stars: 2220
|
||||
owner_login: codingforentrepreneurs
|
||||
owner_html_url: https://github.com/codingforentrepreneurs
|
||||
- name: langserve
|
||||
html_url: https://github.com/langchain-ai/langserve
|
||||
stars: 2215
|
||||
stars: 2240
|
||||
owner_login: langchain-ai
|
||||
owner_html_url: https://github.com/langchain-ai
|
||||
- name: 30-Days-of-Python
|
||||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
|
||||
stars: 2234
|
||||
owner_login: codingforentrepreneurs
|
||||
owner_html_url: https://github.com/codingforentrepreneurs
|
||||
- name: solara
|
||||
html_url: https://github.com/widgetti/solara
|
||||
stars: 2122
|
||||
stars: 2144
|
||||
owner_login: widgetti
|
||||
owner_html_url: https://github.com/widgetti
|
||||
- name: mangum
|
||||
html_url: https://github.com/Kludex/mangum
|
||||
stars: 2029
|
||||
stars: 2051
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: NoteDiscovery
|
||||
html_url: https://github.com/gamosoft/NoteDiscovery
|
||||
stars: 2038
|
||||
owner_login: gamosoft
|
||||
owner_html_url: https://github.com/gamosoft
|
||||
- name: fastapi_best_architecture
|
||||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
|
||||
stars: 1985
|
||||
owner_login: fastapi-practices
|
||||
owner_html_url: https://github.com/fastapi-practices
|
||||
- name: agentkit
|
||||
html_url: https://github.com/BCG-X-Official/agentkit
|
||||
stars: 1912
|
||||
stars: 1936
|
||||
owner_login: BCG-X-Official
|
||||
owner_html_url: https://github.com/BCG-X-Official
|
||||
- name: vue-fastapi-admin
|
||||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
|
||||
stars: 1930
|
||||
owner_login: mizhexiaoxiao
|
||||
owner_html_url: https://github.com/mizhexiaoxiao
|
||||
- name: manage-fastapi
|
||||
html_url: https://github.com/ycd/manage-fastapi
|
||||
stars: 1885
|
||||
stars: 1893
|
||||
owner_login: ycd
|
||||
owner_html_url: https://github.com/ycd
|
||||
- name: openapi-python-client
|
||||
html_url: https://github.com/openapi-generators/openapi-python-client
|
||||
stars: 1862
|
||||
stars: 1885
|
||||
owner_login: openapi-generators
|
||||
owner_html_url: https://github.com/openapi-generators
|
||||
- name: piccolo
|
||||
html_url: https://github.com/piccolo-orm/piccolo
|
||||
stars: 1836
|
||||
owner_login: piccolo-orm
|
||||
owner_html_url: https://github.com/piccolo-orm
|
||||
- name: vue-fastapi-admin
|
||||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
|
||||
stars: 1831
|
||||
owner_login: mizhexiaoxiao
|
||||
owner_html_url: https://github.com/mizhexiaoxiao
|
||||
- name: python-week-2022
|
||||
html_url: https://github.com/rochacbruno/python-week-2022
|
||||
stars: 1817
|
||||
owner_login: rochacbruno
|
||||
owner_html_url: https://github.com/rochacbruno
|
||||
- name: slowapi
|
||||
html_url: https://github.com/laurentS/slowapi
|
||||
stars: 1798
|
||||
stars: 1859
|
||||
owner_login: laurentS
|
||||
owner_html_url: https://github.com/laurentS
|
||||
- name: piccolo
|
||||
html_url: https://github.com/piccolo-orm/piccolo
|
||||
stars: 1848
|
||||
owner_login: piccolo-orm
|
||||
owner_html_url: https://github.com/piccolo-orm
|
||||
- name: python-week-2022
|
||||
html_url: https://github.com/rochacbruno/python-week-2022
|
||||
stars: 1813
|
||||
owner_login: rochacbruno
|
||||
owner_html_url: https://github.com/rochacbruno
|
||||
- name: fastapi-cache
|
||||
html_url: https://github.com/long2ice/fastapi-cache
|
||||
stars: 1789
|
||||
stars: 1808
|
||||
owner_login: long2ice
|
||||
owner_html_url: https://github.com/long2ice
|
||||
- name: ormar
|
||||
html_url: https://github.com/collerek/ormar
|
||||
stars: 1783
|
||||
owner_login: collerek
|
||||
owner_html_url: https://github.com/collerek
|
||||
- name: termpair
|
||||
html_url: https://github.com/cs01/termpair
|
||||
stars: 1716
|
||||
owner_login: cs01
|
||||
owner_html_url: https://github.com/cs01
|
||||
- name: FastAPI-boilerplate
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate
|
||||
stars: 1660
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: fastapi-langgraph-agent-production-ready-template
|
||||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
|
||||
stars: 1638
|
||||
stars: 1808
|
||||
owner_login: wassim249
|
||||
owner_html_url: https://github.com/wassim249
|
||||
- name: langchain-serve
|
||||
html_url: https://github.com/jina-ai/langchain-serve
|
||||
stars: 1635
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: awesome-fastapi-projects
|
||||
html_url: https://github.com/Kludex/awesome-fastapi-projects
|
||||
stars: 1589
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: fastapi-pagination
|
||||
html_url: https://github.com/uriyyo/fastapi-pagination
|
||||
stars: 1585
|
||||
owner_login: uriyyo
|
||||
owner_html_url: https://github.com/uriyyo
|
||||
- name: coronavirus-tracker-api
|
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
|
||||
stars: 1574
|
||||
owner_login: ExpDev07
|
||||
owner_html_url: https://github.com/ExpDev07
|
||||
- name: ormar
|
||||
html_url: https://github.com/collerek/ormar
|
||||
stars: 1787
|
||||
owner_login: collerek
|
||||
owner_html_url: https://github.com/collerek
|
||||
- name: FastAPI-boilerplate
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate
|
||||
stars: 1755
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: termpair
|
||||
html_url: https://github.com/cs01/termpair
|
||||
stars: 1725
|
||||
owner_login: cs01
|
||||
owner_html_url: https://github.com/cs01
|
||||
- name: fastapi-crudrouter
|
||||
html_url: https://github.com/awtkns/fastapi-crudrouter
|
||||
stars: 1559
|
||||
stars: 1673
|
||||
owner_login: awtkns
|
||||
owner_html_url: https://github.com/awtkns
|
||||
- name: langchain-serve
|
||||
html_url: https://github.com/jina-ai/langchain-serve
|
||||
stars: 1631
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: fastapi-pagination
|
||||
html_url: https://github.com/uriyyo/fastapi-pagination
|
||||
stars: 1590
|
||||
owner_login: uriyyo
|
||||
owner_html_url: https://github.com/uriyyo
|
||||
- name: awesome-fastapi-projects
|
||||
html_url: https://github.com/Kludex/awesome-fastapi-projects
|
||||
stars: 1586
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: coronavirus-tracker-api
|
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
|
||||
stars: 1571
|
||||
owner_login: ExpDev07
|
||||
owner_html_url: https://github.com/ExpDev07
|
||||
- name: bracket
|
||||
html_url: https://github.com/evroon/bracket
|
||||
stars: 1489
|
||||
stars: 1554
|
||||
owner_login: evroon
|
||||
owner_html_url: https://github.com/evroon
|
||||
- name: fastapi-amis-admin
|
||||
html_url: https://github.com/amisadmin/fastapi-amis-admin
|
||||
stars: 1475
|
||||
stars: 1499
|
||||
owner_login: amisadmin
|
||||
owner_html_url: https://github.com/amisadmin
|
||||
- name: fastcrud
|
||||
html_url: https://github.com/benavlabs/fastcrud
|
||||
stars: 1455
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: fastapi-boilerplate
|
||||
html_url: https://github.com/teamhide/fastapi-boilerplate
|
||||
stars: 1436
|
||||
stars: 1454
|
||||
owner_login: teamhide
|
||||
owner_html_url: https://github.com/teamhide
|
||||
- name: awesome-python-resources
|
||||
html_url: https://github.com/DjangoEx/awesome-python-resources
|
||||
stars: 1426
|
||||
stars: 1434
|
||||
owner_login: DjangoEx
|
||||
owner_html_url: https://github.com/DjangoEx
|
||||
- name: fastcrud
|
||||
html_url: https://github.com/benavlabs/fastcrud
|
||||
stars: 1414
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: prometheus-fastapi-instrumentator
|
||||
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
|
||||
stars: 1388
|
||||
stars: 1405
|
||||
owner_login: trallnag
|
||||
owner_html_url: https://github.com/trallnag
|
||||
- name: fastapi_best_architecture
|
||||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
|
||||
stars: 1378
|
||||
owner_login: fastapi-practices
|
||||
owner_html_url: https://github.com/fastapi-practices
|
||||
- name: fastapi-code-generator
|
||||
html_url: https://github.com/koxudaxi/fastapi-code-generator
|
||||
stars: 1375
|
||||
stars: 1373
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: fastapi-tutorial
|
||||
html_url: https://github.com/liaogx/fastapi-tutorial
|
||||
stars: 1352
|
||||
owner_login: liaogx
|
||||
owner_html_url: https://github.com/liaogx
|
||||
- name: budgetml
|
||||
html_url: https://github.com/ebhy/budgetml
|
||||
stars: 1345
|
||||
owner_login: ebhy
|
||||
owner_html_url: https://github.com/ebhy
|
||||
- name: fastapi-tutorial
|
||||
html_url: https://github.com/liaogx/fastapi-tutorial
|
||||
stars: 1327
|
||||
owner_login: liaogx
|
||||
owner_html_url: https://github.com/liaogx
|
||||
- name: fastapi-alembic-sqlmodel-async
|
||||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
|
||||
stars: 1259
|
||||
owner_login: jonra1993
|
||||
owner_html_url: https://github.com/jonra1993
|
||||
- name: fastapi-scaff
|
||||
html_url: https://github.com/atpuxiner/fastapi-scaff
|
||||
stars: 1255
|
||||
stars: 1342
|
||||
owner_login: atpuxiner
|
||||
owner_html_url: https://github.com/atpuxiner
|
||||
- name: bedrock-chat
|
||||
html_url: https://github.com/aws-samples/bedrock-chat
|
||||
stars: 1254
|
||||
owner_login: aws-samples
|
||||
owner_html_url: https://github.com/aws-samples
|
||||
- name: bolt-python
|
||||
html_url: https://github.com/slackapi/bolt-python
|
||||
stars: 1253
|
||||
stars: 1269
|
||||
owner_login: slackapi
|
||||
owner_html_url: https://github.com/slackapi
|
||||
- name: bedrock-chat
|
||||
html_url: https://github.com/aws-samples/bedrock-chat
|
||||
stars: 1265
|
||||
owner_login: aws-samples
|
||||
owner_html_url: https://github.com/aws-samples
|
||||
- name: fastapi-alembic-sqlmodel-async
|
||||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
|
||||
stars: 1261
|
||||
owner_login: jonra1993
|
||||
owner_html_url: https://github.com/jonra1993
|
||||
- name: fastapi_production_template
|
||||
html_url: https://github.com/zhanymkanov/fastapi_production_template
|
||||
stars: 1217
|
||||
stars: 1220
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: langchain-extract
|
||||
html_url: https://github.com/langchain-ai/langchain-extract
|
||||
stars: 1176
|
||||
stars: 1178
|
||||
owner_login: langchain-ai
|
||||
owner_html_url: https://github.com/langchain-ai
|
||||
- name: restish
|
||||
html_url: https://github.com/rest-sh/restish
|
||||
stars: 1140
|
||||
stars: 1156
|
||||
owner_login: rest-sh
|
||||
owner_html_url: https://github.com/rest-sh
|
||||
- name: odmantic
|
||||
html_url: https://github.com/art049/odmantic
|
||||
stars: 1138
|
||||
stars: 1145
|
||||
owner_login: art049
|
||||
owner_html_url: https://github.com/art049
|
||||
- name: authx
|
||||
html_url: https://github.com/yezz123/authx
|
||||
stars: 1119
|
||||
stars: 1130
|
||||
owner_login: yezz123
|
||||
owner_html_url: https://github.com/yezz123
|
||||
- name: NoteDiscovery
|
||||
html_url: https://github.com/gamosoft/NoteDiscovery
|
||||
stars: 1107
|
||||
owner_login: gamosoft
|
||||
owner_html_url: https://github.com/gamosoft
|
||||
- name: SAG
|
||||
html_url: https://github.com/Zleap-AI/SAG
|
||||
stars: 1108
|
||||
owner_login: Zleap-AI
|
||||
owner_html_url: https://github.com/Zleap-AI
|
||||
- name: RuoYi-Vue3-FastAPI
|
||||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
|
||||
stars: 1092
|
||||
owner_login: insistence
|
||||
owner_html_url: https://github.com/insistence
|
||||
- name: aktools
|
||||
html_url: https://github.com/akfamily/aktools
|
||||
stars: 1089
|
||||
owner_login: akfamily
|
||||
owner_html_url: https://github.com/akfamily
|
||||
- name: flock
|
||||
html_url: https://github.com/Onelevenvy/flock
|
||||
stars: 1055
|
||||
stars: 1060
|
||||
owner_login: Onelevenvy
|
||||
owner_html_url: https://github.com/Onelevenvy
|
||||
- name: fastapi-observability
|
||||
html_url: https://github.com/blueswen/fastapi-observability
|
||||
stars: 1038
|
||||
stars: 1050
|
||||
owner_login: blueswen
|
||||
owner_html_url: https://github.com/blueswen
|
||||
- name: aktools
|
||||
html_url: https://github.com/akfamily/aktools
|
||||
stars: 1027
|
||||
owner_login: akfamily
|
||||
owner_html_url: https://github.com/akfamily
|
||||
- name: RuoYi-Vue3-FastAPI
|
||||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
|
||||
stars: 1016
|
||||
owner_login: insistence
|
||||
owner_html_url: https://github.com/insistence
|
||||
- name: autollm
|
||||
html_url: https://github.com/viddexa/autollm
|
||||
stars: 1002
|
||||
owner_login: viddexa
|
||||
owner_html_url: https://github.com/viddexa
|
||||
- name: titiler
|
||||
html_url: https://github.com/developmentseed/titiler
|
||||
stars: 999
|
||||
owner_login: developmentseed
|
||||
owner_html_url: https://github.com/developmentseed
|
||||
- name: lanarky
|
||||
html_url: https://github.com/ajndkr/lanarky
|
||||
stars: 994
|
||||
owner_login: ajndkr
|
||||
owner_html_url: https://github.com/ajndkr
|
||||
- name: every-pdf
|
||||
html_url: https://github.com/DDULDDUCK/every-pdf
|
||||
stars: 985
|
||||
owner_login: DDULDDUCK
|
||||
owner_html_url: https://github.com/DDULDDUCK
|
||||
- name: enterprise-deep-research
|
||||
html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research
|
||||
stars: 973
|
||||
stars: 1028
|
||||
owner_login: SalesforceAIResearch
|
||||
owner_html_url: https://github.com/SalesforceAIResearch
|
||||
- name: fastapi-mail
|
||||
html_url: https://github.com/sabuhish/fastapi-mail
|
||||
stars: 964
|
||||
owner_login: sabuhish
|
||||
owner_html_url: https://github.com/sabuhish
|
||||
- name: titiler
|
||||
html_url: https://github.com/developmentseed/titiler
|
||||
stars: 1020
|
||||
owner_login: developmentseed
|
||||
owner_html_url: https://github.com/developmentseed
|
||||
- name: every-pdf
|
||||
html_url: https://github.com/DDULDDUCK/every-pdf
|
||||
stars: 1005
|
||||
owner_login: DDULDDUCK
|
||||
owner_html_url: https://github.com/DDULDDUCK
|
||||
- name: autollm
|
||||
html_url: https://github.com/viddexa/autollm
|
||||
stars: 1004
|
||||
owner_login: viddexa
|
||||
owner_html_url: https://github.com/viddexa
|
||||
- name: lanarky
|
||||
html_url: https://github.com/ajndkr/lanarky
|
||||
stars: 996
|
||||
owner_login: ajndkr
|
||||
owner_html_url: https://github.com/ajndkr
|
||||
|
||||
@@ -15,7 +15,7 @@ sodaMelon:
|
||||
url: https://github.com/sodaMelon
|
||||
ceb10n:
|
||||
login: ceb10n
|
||||
count: 116
|
||||
count: 117
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
tokusumi:
|
||||
@@ -23,16 +23,16 @@ tokusumi:
|
||||
count: 104
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
hard-coders:
|
||||
login: hard-coders
|
||||
count: 96
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
hasansezertasan:
|
||||
login: hasansezertasan
|
||||
count: 95
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4
|
||||
url: https://github.com/hasansezertasan
|
||||
hard-coders:
|
||||
login: hard-coders
|
||||
count: 93
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
alv2017:
|
||||
login: alv2017
|
||||
count: 88
|
||||
@@ -40,7 +40,7 @@ alv2017:
|
||||
url: https://github.com/alv2017
|
||||
nazarepiedady:
|
||||
login: nazarepiedady
|
||||
count: 86
|
||||
count: 87
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=f69ddc4ea8bda3bdfac7aa0e2ea38de282e6ee2d&v=4
|
||||
url: https://github.com/nazarepiedady
|
||||
AlertRED:
|
||||
@@ -48,6 +48,11 @@ AlertRED:
|
||||
count: 81
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4
|
||||
url: https://github.com/AlertRED
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 73
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
Alexandrhub:
|
||||
login: Alexandrhub
|
||||
count: 68
|
||||
@@ -63,21 +68,16 @@ cassiobotaro:
|
||||
count: 62
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4
|
||||
url: https://github.com/cassiobotaro
|
||||
mattwang44:
|
||||
login: mattwang44
|
||||
count: 61
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4
|
||||
url: https://github.com/mattwang44
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 59
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
mattwang44:
|
||||
login: mattwang44
|
||||
count: 59
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4
|
||||
url: https://github.com/mattwang44
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 56
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
Laineyzhang55:
|
||||
login: Laineyzhang55
|
||||
count: 48
|
||||
@@ -88,6 +88,11 @@ Kludex:
|
||||
count: 47
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
|
||||
url: https://github.com/Kludex
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
komtaki:
|
||||
login: komtaki
|
||||
count: 45
|
||||
@@ -118,11 +123,6 @@ Winand:
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53390?u=bb0e71a2fc3910a8e0ee66da67c33de40ea695f8&v=4
|
||||
url: https://github.com/Winand
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
solomein-sv:
|
||||
login: solomein-sv
|
||||
count: 38
|
||||
@@ -138,6 +138,11 @@ alejsdev:
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
mezgoodle:
|
||||
login: mezgoodle
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4
|
||||
url: https://github.com/mezgoodle
|
||||
stlucasgarcia:
|
||||
login: stlucasgarcia
|
||||
count: 36
|
||||
@@ -153,11 +158,6 @@ timothy-jeong:
|
||||
count: 36
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4
|
||||
url: https://github.com/timothy-jeong
|
||||
mezgoodle:
|
||||
login: mezgoodle
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4
|
||||
url: https://github.com/mezgoodle
|
||||
rjNemo:
|
||||
login: rjNemo
|
||||
count: 34
|
||||
@@ -173,6 +173,11 @@ akarev0:
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53393089?u=6e528bb4789d56af887ce6fe237bea4010885406&v=4
|
||||
url: https://github.com/akarev0
|
||||
Vincy1230:
|
||||
login: Vincy1230
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4
|
||||
url: https://github.com/Vincy1230
|
||||
romashevchenko:
|
||||
login: romashevchenko
|
||||
count: 32
|
||||
@@ -183,11 +188,6 @@ LorhanSohaky:
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
||||
url: https://github.com/LorhanSohaky
|
||||
Vincy1230:
|
||||
login: Vincy1230
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4
|
||||
url: https://github.com/Vincy1230
|
||||
black-redoc:
|
||||
login: black-redoc
|
||||
count: 29
|
||||
@@ -250,7 +250,7 @@ mycaule:
|
||||
url: https://github.com/mycaule
|
||||
Aruelius:
|
||||
login: Aruelius
|
||||
count: 24
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25380989?u=574f8cfcda3ea77a3f81884f6b26a97068e36a9d&v=4
|
||||
url: https://github.com/Aruelius
|
||||
wisderfin:
|
||||
@@ -263,6 +263,11 @@ OzgunCaglarArslan:
|
||||
count: 24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/86166426?v=4
|
||||
url: https://github.com/OzgunCaglarArslan
|
||||
ycd:
|
||||
login: ycd
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4
|
||||
url: https://github.com/ycd
|
||||
sh0nk:
|
||||
login: sh0nk
|
||||
count: 23
|
||||
@@ -288,11 +293,6 @@ Attsun1031:
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
||||
url: https://github.com/Attsun1031
|
||||
ycd:
|
||||
login: ycd
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4
|
||||
url: https://github.com/ycd
|
||||
delhi09:
|
||||
login: delhi09
|
||||
count: 20
|
||||
@@ -418,6 +418,11 @@ mattkoehne:
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4
|
||||
url: https://github.com/mattkoehne
|
||||
maru0123-2004:
|
||||
login: maru0123-2004
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4
|
||||
url: https://github.com/maru0123-2004
|
||||
jovicon:
|
||||
login: jovicon
|
||||
count: 13
|
||||
@@ -443,6 +448,11 @@ impocode:
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109408819?u=9cdfc5ccb31a2094c520f41b6087012fa9048982&v=4
|
||||
url: https://github.com/impocode
|
||||
waketzheng:
|
||||
login: waketzheng
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4
|
||||
url: https://github.com/waketzheng
|
||||
wesinalves:
|
||||
login: wesinalves
|
||||
count: 13
|
||||
@@ -538,21 +548,16 @@ Lufa1u:
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/112495876?u=087658920ed9e74311597bdd921d8d2de939d276&v=4
|
||||
url: https://github.com/Lufa1u
|
||||
waketzheng:
|
||||
login: waketzheng
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4
|
||||
url: https://github.com/waketzheng
|
||||
KNChiu:
|
||||
login: KNChiu
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4
|
||||
url: https://github.com/KNChiu
|
||||
maru0123-2004:
|
||||
login: maru0123-2004
|
||||
Zhongheng-Cheng:
|
||||
login: Zhongheng-Cheng
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4
|
||||
url: https://github.com/maru0123-2004
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4
|
||||
url: https://github.com/Zhongheng-Cheng
|
||||
mariacamilagl:
|
||||
login: mariacamilagl
|
||||
count: 10
|
||||
@@ -608,16 +613,16 @@ nick-cjyx9:
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=7227a2de948c68fb8396d5beff1ee5b0e057c42e&v=4
|
||||
url: https://github.com/nick-cjyx9
|
||||
marcelomarkus:
|
||||
login: marcelomarkus
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20115018?u=dda090ce9160ef0cd2ff69b1e5ea741283425cba&v=4
|
||||
url: https://github.com/marcelomarkus
|
||||
lucasbalieiro:
|
||||
login: lucasbalieiro
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=d144221c34c08adac8b20e1833d776ffa1c4b1d0&v=4
|
||||
url: https://github.com/lucasbalieiro
|
||||
Zhongheng-Cheng:
|
||||
login: Zhongheng-Cheng
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4
|
||||
url: https://github.com/Zhongheng-Cheng
|
||||
RunningIkkyu:
|
||||
login: RunningIkkyu
|
||||
count: 9
|
||||
@@ -668,11 +673,6 @@ yodai-yodai:
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7031039?u=4f3593f5931892b931a745cfab846eff6e9332e7&v=4
|
||||
url: https://github.com/yodai-yodai
|
||||
marcelomarkus:
|
||||
login: marcelomarkus
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20115018?u=dda090ce9160ef0cd2ff69b1e5ea741283425cba&v=4
|
||||
url: https://github.com/marcelomarkus
|
||||
JoaoGustavoRogel:
|
||||
login: JoaoGustavoRogel
|
||||
count: 9
|
||||
@@ -683,6 +683,11 @@ Yarous:
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4
|
||||
url: https://github.com/Yarous
|
||||
Pyth3rEx:
|
||||
login: Pyth3rEx
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4
|
||||
url: https://github.com/Pyth3rEx
|
||||
dimaqq:
|
||||
login: dimaqq
|
||||
count: 8
|
||||
@@ -1023,6 +1028,11 @@ devluisrodrigues:
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4
|
||||
url: https://github.com/11kkw
|
||||
EdmilsonRodrigues:
|
||||
login: EdmilsonRodrigues
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
|
||||
url: https://github.com/EdmilsonRodrigues
|
||||
lpdswing:
|
||||
login: lpdswing
|
||||
count: 4
|
||||
@@ -1163,6 +1173,11 @@ AbolfazlKameli:
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=af8f025278cce0d489007071254e4055df60b78c&v=4
|
||||
url: https://github.com/AbolfazlKameli
|
||||
SBillion:
|
||||
login: SBillion
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1070649?u=3ab493dfc88b39da0eb1600e3b8e7df1c90a5dee&v=4
|
||||
url: https://github.com/SBillion
|
||||
tyronedamasceno:
|
||||
login: tyronedamasceno
|
||||
count: 3
|
||||
@@ -1211,7 +1226,7 @@ phamquanganh31101998:
|
||||
peebbv6364:
|
||||
login: peebbv6364
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26784747?u=75583df215ee01a5cd2dc646aecb81e7dbd33d06&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26784747?u=3bf07017eb4f4fa3639ba8d4ed19980a34bf8f90&v=4
|
||||
url: https://github.com/peebbv6364
|
||||
mrparalon:
|
||||
login: mrparalon
|
||||
@@ -1413,11 +1428,6 @@ Mohammad222PR:
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4
|
||||
url: https://github.com/Mohammad222PR
|
||||
EdmilsonRodrigues:
|
||||
login: EdmilsonRodrigues
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
|
||||
url: https://github.com/EdmilsonRodrigues
|
||||
blaisep:
|
||||
login: blaisep
|
||||
count: 2
|
||||
@@ -1838,11 +1848,11 @@ NavesSapnis:
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4
|
||||
url: https://github.com/NavesSapnis
|
||||
eqsdxr:
|
||||
login: eqsdxr
|
||||
isgin01:
|
||||
login: isgin01
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=7927dc0366995334f9a18c3204a41d3a34d6d96f&v=4
|
||||
url: https://github.com/eqsdxr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=ddffde10876b50f35dc90d1337f507a630530a6a&v=4
|
||||
url: https://github.com/isgin01
|
||||
syedasamina56:
|
||||
login: syedasamina56
|
||||
count: 2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 125
|
||||
count: 130
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
jaystone776:
|
||||
@@ -28,6 +28,11 @@ SwftAlpc:
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||
url: https://github.com/SwftAlpc
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
hasansezertasan:
|
||||
login: hasansezertasan
|
||||
count: 22
|
||||
@@ -46,7 +51,7 @@ AlertRED:
|
||||
hard-coders:
|
||||
login: hard-coders
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
Joao-Pedro-P-Holanda:
|
||||
login: Joao-Pedro-P-Holanda
|
||||
@@ -103,11 +108,6 @@ pablocm83:
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4
|
||||
url: https://github.com/pablocm83
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
ptt3199:
|
||||
login: ptt3199
|
||||
count: 7
|
||||
@@ -126,13 +126,18 @@ batlopes:
|
||||
lucasbalieiro:
|
||||
login: lucasbalieiro
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=d144221c34c08adac8b20e1833d776ffa1c4b1d0&v=4
|
||||
url: https://github.com/lucasbalieiro
|
||||
Alexandrhub:
|
||||
login: Alexandrhub
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4
|
||||
url: https://github.com/Alexandrhub
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
Serrones:
|
||||
login: Serrones
|
||||
count: 5
|
||||
@@ -358,11 +363,6 @@ ruzia:
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4
|
||||
url: https://github.com/ruzia
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
izaguerreiro:
|
||||
login: izaguerreiro
|
||||
count: 2
|
||||
|
||||
@@ -6,7 +6,7 @@ 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`.
|
||||
* 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.
|
||||
|
||||
@@ -6,44 +6,20 @@ First, you might want to see the basic ways to [help FastAPI and get help](help-
|
||||
|
||||
If you already cloned the <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">fastapi repository</a> and you want to deep dive in the code, here are some guidelines to set up your environment.
|
||||
|
||||
### Virtual environment
|
||||
|
||||
Follow the instructions to create and activate a [virtual environment](virtual-environments.md){.internal-link target=_blank} for the internal code of `fastapi`.
|
||||
|
||||
### Install requirements
|
||||
|
||||
After activating the environment, install the required packages:
|
||||
|
||||
//// tab | `pip`
|
||||
Create a virtual environment and install the required packages with <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install -r requirements.txt
|
||||
$ uv sync
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | `uv`
|
||||
|
||||
If you have <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uv pip install -r requirements.txt
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
It will install all the dependencies and your local FastAPI in your local environment.
|
||||
|
||||
### Using your local FastAPI
|
||||
@@ -56,9 +32,9 @@ That way, you don't have to "install" your local version to be able to test ever
|
||||
|
||||
/// note | Technical Details
|
||||
|
||||
This only happens when you install using this included `requirements.txt` instead of running `pip install fastapi` directly.
|
||||
This only happens when you install using `uv sync` instead of running `pip install fastapi` directly.
|
||||
|
||||
That is because inside the `requirements.txt` file, the local version of FastAPI is marked to be installed in "editable" mode, with the `-e` option.
|
||||
That is because `uv sync` will install the local version of FastAPI in "editable" mode by default.
|
||||
|
||||
///
|
||||
|
||||
|
||||
@@ -7,6 +7,23 @@ hide:
|
||||
|
||||
## Latest Changes
|
||||
|
||||
### Translations
|
||||
|
||||
* 🔧 Add LLM prompt file for Turkish, generated from the existing translations. PR [#14547](https://github.com/fastapi/fastapi/pull/14547) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add LLM prompt file for Traditional Chinese, generated from the existing translations. PR [#14550](https://github.com/fastapi/fastapi/pull/14550) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add LLM prompt file for Simplified Chinese, generated from the existing translations. PR [#14549](https://github.com/fastapi/fastapi/pull/14549) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People - Sponsors. PR [#14626](https://github.com/fastapi/fastapi/pull/14626) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI GitHub topic repositories. PR [#14630](https://github.com/fastapi/fastapi/pull/14630) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People - Contributors and Translators. PR [#14625](https://github.com/fastapi/fastapi/pull/14625) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🌐 Update translation prompts. PR [#14619](https://github.com/fastapi/fastapi/pull/14619) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔨 Update LLM translation script to guide reviewers to change the prompt. PR [#14614](https://github.com/fastapi/fastapi/pull/14614) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Do not run translations on cron while finishing updating existing languages. PR [#14613](https://github.com/fastapi/fastapi/pull/14613) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔥 Remove test variants for Pydantic v1 in test_request_params. PR [#14612](https://github.com/fastapi/fastapi/pull/14612) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔥 Remove Pydantic v1 specific test variants. PR [#14611](https://github.com/fastapi/fastapi/pull/14611) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.128.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -6,23 +6,23 @@ Language code: ja.
|
||||
|
||||
### Grammar and tone
|
||||
|
||||
1) Use polite, instructional Japanese (です/ます調).
|
||||
2) Keep the tone concise and technical (match existing Japanese FastAPI docs).
|
||||
- Use polite, instructional Japanese (です/ます調).
|
||||
- Keep the tone concise and technical (match existing Japanese FastAPI docs).
|
||||
|
||||
### Headings
|
||||
|
||||
1) Follow the existing Japanese style: short, descriptive headings (often noun phrases), e.g. 「チェック」.
|
||||
2) Do not add a trailing period at the end of headings.
|
||||
- Follow the existing Japanese style: short, descriptive headings (often noun phrases), e.g. 「チェック」.
|
||||
- Do not add a trailing period at the end of headings.
|
||||
|
||||
### Quotes
|
||||
|
||||
1) Prefer Japanese corner brackets 「」 in normal prose when quoting a term.
|
||||
2) Do not change quotes inside inline code, code blocks, URLs, or file paths.
|
||||
- Prefer Japanese corner brackets 「」 in normal prose when quoting a term.
|
||||
- Do not change quotes inside inline code, code blocks, URLs, or file paths.
|
||||
|
||||
### Ellipsis
|
||||
|
||||
1) Keep ellipsis style consistent with existing Japanese docs (commonly `...`).
|
||||
2) Never change `...` in code, URLs, or CLI examples.
|
||||
- Keep ellipsis style consistent with existing Japanese docs (commonly `...`).
|
||||
- Never change `...` in code, URLs, or CLI examples.
|
||||
|
||||
### Preferred translations / glossary
|
||||
|
||||
|
||||
@@ -6,23 +6,23 @@ Language code: ko.
|
||||
|
||||
### Grammar and tone
|
||||
|
||||
1) Use polite, instructional Korean (e.g. 합니다/하세요 style).
|
||||
2) Keep the tone consistent with the existing Korean FastAPI docs.
|
||||
- Use polite, instructional Korean (e.g. 합니다/하세요 style).
|
||||
- Keep the tone consistent with the existing Korean FastAPI docs.
|
||||
|
||||
### Headings
|
||||
|
||||
1) Follow existing Korean heading style (short, action-oriented headings like “확인하기”).
|
||||
2) Do not add trailing punctuation to headings.
|
||||
- Follow existing Korean heading style (short, action-oriented headings like “확인하기”).
|
||||
- Do not add trailing punctuation to headings.
|
||||
|
||||
### Quotes
|
||||
|
||||
1) Keep quote style consistent with the existing Korean docs.
|
||||
2) Never change quotes inside inline code, code blocks, URLs, or file paths.
|
||||
- Keep quote style consistent with the existing Korean docs.
|
||||
- Never change quotes inside inline code, code blocks, URLs, or file paths.
|
||||
|
||||
### Ellipsis
|
||||
|
||||
1) Keep ellipsis style consistent with existing Korean docs (often `...`).
|
||||
2) Never change `...` in code, URLs, or CLI examples.
|
||||
- Keep ellipsis style consistent with existing Korean docs (often `...`).
|
||||
- Never change `...` in code, URLs, or CLI examples.
|
||||
|
||||
### Preferred translations / glossary
|
||||
|
||||
|
||||
@@ -4,6 +4,6 @@ This page hasn’t been translated into your language yet. 🌍
|
||||
|
||||
We’re currently switching to an automated translation system 🤖, which will help keep all translations complete and up to date.
|
||||
|
||||
Learn more: [Contributing – Translations](https://fastapi.tiangolo.com/contributing/#translations){.internal-link target=_blank}
|
||||
Learn more: [Contributing - Translations](https://fastapi.tiangolo.com/contributing/#translations){.internal-link target=_blank}
|
||||
|
||||
///
|
||||
|
||||
@@ -14,15 +14,15 @@ When translating documentation into Portuguese, use neutral and widely understan
|
||||
|
||||
For the next terms, use the following translations:
|
||||
|
||||
* «/// check»: «/// check | Verifique»
|
||||
* «/// danger»: «/// danger | Cuidado»
|
||||
* «/// info»: «/// info | Informação»
|
||||
* «/// note | Technical Details»: «/// note | Detalhes Técnicos»
|
||||
* «/// info | Very Technical Details»: «/// note | Detalhes Técnicos Avançados»
|
||||
* «/// note»: «/// note | Nota»
|
||||
* «/// tip»: «/// tip | Dica»
|
||||
* «/// warning»: «/// warning | Atenção»
|
||||
* «(you should)»: «(você deveria)»
|
||||
* /// check: /// check | Verifique
|
||||
* /// danger: /// danger | Cuidado
|
||||
* /// info: /// info | Informação
|
||||
* /// note | Technical Details: /// note | Detalhes Técnicos
|
||||
* /// info | Very Technical Details: /// note | Detalhes Técnicos Avançados
|
||||
* /// note: /// note | Nota
|
||||
* /// tip: /// tip | Dica
|
||||
* /// warning: /// warning | Atenção
|
||||
* (you should): (você deveria)
|
||||
* async context manager: gerenciador de contexto assíncrono
|
||||
* autocomplete: autocompletar
|
||||
* autocompletion: preenchimento automático
|
||||
|
||||
52
docs/tr/llm-prompt.md
Normal file
52
docs/tr/llm-prompt.md
Normal file
@@ -0,0 +1,52 @@
|
||||
### Target language
|
||||
|
||||
Translate to Turkish (Türkçe).
|
||||
|
||||
Language code: tr.
|
||||
|
||||
### Grammar and tone
|
||||
|
||||
- Use instructional Turkish, consistent with existing Turkish docs.
|
||||
- Use imperative/guide language when appropriate (e.g. “açalım”, “gidin”, “kopyalayalım”).
|
||||
|
||||
### Headings
|
||||
|
||||
- Follow existing Turkish heading style (Title Case where used; no trailing period).
|
||||
|
||||
### Quotes
|
||||
|
||||
- Alıntı stili mevcut Türkçe dokümanlarla tutarlı tutun (genellikle metin içinde ASCII tırnak işaretleri kullanılır).
|
||||
- Satır içi kod, kod blokları, URL'ler veya dosya yolları içindeki tırnak işaretlerini asla değiştirmeyin.
|
||||
|
||||
### Ellipsis
|
||||
|
||||
- Üç nokta (...) stili mevcut Türkçe dokümanlarla tutarlı tutun.
|
||||
- Kod, URL veya CLI örneklerindeki `...` ifadesini asla değiştirmeyin.
|
||||
|
||||
### Preferred translations / glossary
|
||||
|
||||
Do not translate technical terms like path, route, request, response, query, body, cookie, and header, keep them as is.
|
||||
|
||||
- Suffixing is very important, when adding Turkish suffixes to the English words, do that based on the pronunciation of the word and with an apostrophe.
|
||||
|
||||
- Suffixes also changes based on what word comes next in Turkish too, here is an example:
|
||||
|
||||
"Server'a gelen request'leri intercept... " or this could have been "request'e", "request'i" etc.
|
||||
|
||||
- Some words are tricky like "path'e" can't be used like "path'a" but it could have been "path'i" "path'leri" etc.
|
||||
|
||||
- You can use a more instructional style, that is consistent with the document, you can add the Turkish version of the term in parenthesis if it is not something very obvious, or an advanced concept, but do not over do it, do it only the first time it is mentioned, but keep the English term as the primary word.
|
||||
|
||||
### `///` admonitions
|
||||
|
||||
- Keep the admonition keyword in English (do not translate `note`, `tip`, etc.).
|
||||
- If a title is present, prefer these canonical titles:
|
||||
|
||||
- `/// note | Not`
|
||||
- `/// note | Teknik Detaylar`
|
||||
- `/// tip | İpucu`
|
||||
- `/// warning | Uyarı`
|
||||
- `/// info | Bilgi`
|
||||
- `/// check | Ek bilgi`
|
||||
|
||||
Prefer `İpucu` over `Ipucu`.
|
||||
@@ -6,23 +6,23 @@ Language code: uk.
|
||||
|
||||
### Grammar and tone
|
||||
|
||||
1) Use polite/formal address consistent with existing Ukrainian docs (use “ви/ваш”).
|
||||
2) Keep the tone concise and technical.
|
||||
- Use polite/formal address consistent with existing Ukrainian docs (use “ви/ваш”).
|
||||
- Keep the tone concise and technical.
|
||||
|
||||
### Headings
|
||||
|
||||
1) Follow existing Ukrainian heading style; keep headings short and instructional.
|
||||
2) Do not add trailing punctuation to headings.
|
||||
- Follow existing Ukrainian heading style; keep headings short and instructional.
|
||||
- Do not add trailing punctuation to headings.
|
||||
|
||||
### Quotes
|
||||
|
||||
1) Prefer Ukrainian guillemets «…» for quoted terms in prose, matching existing Ukrainian docs.
|
||||
2) Never change quotes inside inline code, code blocks, URLs, or file paths.
|
||||
- Prefer Ukrainian guillemets «…» for quoted terms in prose, matching existing Ukrainian docs.
|
||||
- Never change quotes inside inline code, code blocks, URLs, or file paths.
|
||||
|
||||
### Ellipsis
|
||||
|
||||
1) Keep ellipsis style consistent with existing Ukrainian docs.
|
||||
2) Never change `...` in code, URLs, or CLI examples.
|
||||
- Keep ellipsis style consistent with existing Ukrainian docs.
|
||||
- Never change `...` in code, URLs, or CLI examples.
|
||||
|
||||
### Preferred translations / glossary
|
||||
|
||||
@@ -35,8 +35,8 @@ Use the following preferred translations when they apply in documentation prose:
|
||||
|
||||
### `///` admonitions
|
||||
|
||||
1) Keep the admonition keyword in English (do not translate `note`, `tip`, etc.).
|
||||
2) If a title is present, prefer these canonical titles (choose one canonical form where variants exist):
|
||||
- Keep the admonition keyword in English (do not translate `note`, `tip`, etc.).
|
||||
- If a title is present, prefer these canonical titles (choose one canonical form where variants exist):
|
||||
|
||||
- `/// note | Примітка`
|
||||
- `/// note | Технічні деталі`
|
||||
|
||||
60
docs/zh-hant/llm-prompt.md
Normal file
60
docs/zh-hant/llm-prompt.md
Normal file
@@ -0,0 +1,60 @@
|
||||
### Target language
|
||||
|
||||
Translate to Traditional Chinese (繁體中文).
|
||||
|
||||
Language code: zh-hant.
|
||||
|
||||
### Grammar and tone
|
||||
|
||||
- Use clear, concise technical Traditional Chinese consistent with existing docs.
|
||||
- Address the reader naturally (commonly using “你/你的”).
|
||||
|
||||
### Headings
|
||||
|
||||
- Follow existing Traditional Chinese heading style (short and descriptive).
|
||||
- Do not add trailing punctuation to headings.
|
||||
|
||||
### Quotes and punctuation
|
||||
|
||||
- Keep punctuation style consistent with existing Traditional Chinese docs (they often mix English terms like “FastAPI” with Chinese text).
|
||||
- Never change punctuation inside inline code, code blocks, URLs, or file paths.
|
||||
- For more details, please follow the [Chinese Copywriting Guidelines](https://github.com/sparanoid/chinese-copywriting-guidelines).
|
||||
|
||||
### Ellipsis
|
||||
|
||||
- Keep ellipsis style consistent within each document, prefer `...` over `……`.
|
||||
- Never change ellipsis in code, URLs, or CLI examples.
|
||||
|
||||
### Preferred translations / glossary
|
||||
|
||||
- Should avoid using simplified Chinese characters and terms. Always examine if the translation can be easily comprehended by the Traditional Chinese readers.
|
||||
- For some Python-specific terms like "pickle", "list", "dict" etc, we don't have to translate them.
|
||||
- Use the following preferred translations when they apply in documentation prose:
|
||||
|
||||
- request (HTTP): 請求
|
||||
- response (HTTP): 回應
|
||||
- path operation: 路徑操作
|
||||
- path operation function: 路徑操作函式
|
||||
|
||||
The translation can optionally include the original English text only in the first occurrence of each page (e.g. "路徑操作 (path operation)") if the translation is hard to be comprehended by most of the Chinese readers.
|
||||
|
||||
### `///` admonitions
|
||||
|
||||
1) Keep the admonition keyword in English (do not translate `note`, `tip`, etc.).
|
||||
2) Many Traditional Chinese docs currently omit titles in `///` blocks; that is OK.
|
||||
3) If a generic title is present, prefer these canonical titles:
|
||||
|
||||
- `/// note | 注意`
|
||||
|
||||
Notes:
|
||||
|
||||
- `details` blocks exist; keep `/// details` as-is and translate only the title after `|`.
|
||||
- Example canonical titles used in existing docs:
|
||||
|
||||
```
|
||||
/// details | 上述指令的含義
|
||||
```
|
||||
|
||||
```
|
||||
/// details | 關於 `requirements.txt`
|
||||
```
|
||||
46
docs/zh/llm-prompt.md
Normal file
46
docs/zh/llm-prompt.md
Normal file
@@ -0,0 +1,46 @@
|
||||
### Target language
|
||||
|
||||
Translate to Simplified Chinese (简体中文).
|
||||
|
||||
Language code: zh.
|
||||
|
||||
### Grammar and tone
|
||||
|
||||
- Use clear, concise technical Chinese consistent with existing docs.
|
||||
- Address the reader naturally (commonly using “你/你的”).
|
||||
|
||||
### Headings
|
||||
|
||||
- Follow existing Simplified Chinese heading style (short and descriptive).
|
||||
- Do not add trailing punctuation to headings.
|
||||
- If a heading contains only the name of a FastAPI feature, do not translate it.
|
||||
|
||||
### Quotes and punctuation
|
||||
|
||||
- Keep punctuation style consistent with existing Simplified Chinese docs (they often mix English terms like “FastAPI” with Chinese text).
|
||||
- Never change punctuation inside inline code, code blocks, URLs, or file paths.
|
||||
|
||||
### Ellipsis
|
||||
|
||||
- Keep ellipsis style consistent within each document, prefer `...` over `……`.
|
||||
- Never change ellipsis in code, URLs, or CLI examples.
|
||||
|
||||
### Preferred translations / glossary
|
||||
|
||||
Use the following preferred translations when they apply in documentation prose:
|
||||
|
||||
- request (HTTP): 请求
|
||||
- response (HTTP): 响应
|
||||
- path operation: 路径操作
|
||||
- path operation function: 路径操作函数
|
||||
|
||||
### `///` admonitions
|
||||
|
||||
- Keep the admonition keyword in English (do not translate `note`, `tip`, etc.).
|
||||
- If a title is present, prefer these canonical titles:
|
||||
|
||||
- `/// tip | 提示`
|
||||
- `/// note | 注意`
|
||||
- `/// warning | 警告`
|
||||
- `/// info | 信息`
|
||||
- `/// danger | 危险`
|
||||
@@ -123,6 +123,68 @@ all = [
|
||||
[project.scripts]
|
||||
fastapi = "fastapi.cli:main"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
{ include-group = "tests" },
|
||||
{ include-group = "docs" },
|
||||
{ include-group = "translations" },
|
||||
"playwright>=1.57.0",
|
||||
"prek==0.2.22",
|
||||
]
|
||||
docs = [
|
||||
{ include-group = "docs-tests" },
|
||||
"black==25.1.0",
|
||||
"cairosvg==2.8.2",
|
||||
"griffe-typingdoc==0.3.0",
|
||||
"griffe-warnings-deprecated==1.1.0",
|
||||
"jieba==0.42.1",
|
||||
"markdown-include-variants==0.0.8",
|
||||
"mdx-include>=1.4.1,<2.0.0",
|
||||
"mkdocs-macros-plugin==1.4.1",
|
||||
"mkdocs-material==9.7.0",
|
||||
"mkdocs-redirects>=1.2.1,<1.3.0",
|
||||
"mkdocstrings[python]==0.30.1",
|
||||
"pillow==11.3.0",
|
||||
"python-slugify==8.0.4",
|
||||
"pyyaml>=5.3.1,<7.0.0",
|
||||
"typer==0.16.0",
|
||||
]
|
||||
docs-tests = [
|
||||
"httpx>=0.23.0,<1.0.0",
|
||||
"ruff==0.14.3",
|
||||
]
|
||||
github-actions = [
|
||||
"httpx>=0.27.0,<1.0.0",
|
||||
"pydantic>=2.5.3,<3.0.0",
|
||||
"pydantic-settings>=2.1.0,<3.0.0",
|
||||
"pygithub>=2.3.0,<3.0.0",
|
||||
"pyyaml>=5.3.1,<7.0.0",
|
||||
"smokeshow>=0.5.0",
|
||||
]
|
||||
tests = [
|
||||
{ include-group = "docs-tests" },
|
||||
"anyio[trio]>=3.2.1,<5.0.0",
|
||||
"coverage[toml]>=6.5.0,<8.0",
|
||||
"dirty-equals==0.9.0",
|
||||
"flask>=1.1.2,<4.0.0",
|
||||
"inline-snapshot>=0.21.1",
|
||||
"mypy==1.14.1",
|
||||
"pwdlib[argon2]>=0.2.1",
|
||||
"pyjwt==2.9.0",
|
||||
"pytest>=7.1.3,<9.0.0",
|
||||
"pytest-codspeed==4.2.0",
|
||||
"pyyaml>=5.3.1,<7.0.0",
|
||||
"sqlmodel==0.0.27",
|
||||
"strawberry-graphql>=0.200.0,<1.0.0",
|
||||
"types-orjson==3.6.2",
|
||||
"types-ujson==5.10.0.20240515",
|
||||
]
|
||||
translations = [
|
||||
"gitpython==3.1.45",
|
||||
"pydantic-ai==0.4.10",
|
||||
"pygithub==2.8.1",
|
||||
]
|
||||
|
||||
[tool.pdm]
|
||||
version = { source = "file", path = "fastapi/__init__.py" }
|
||||
distribution = true
|
||||
@@ -131,11 +193,10 @@ distribution = true
|
||||
source-includes = [
|
||||
"tests/",
|
||||
"docs_src/",
|
||||
"requirements*.txt",
|
||||
"scripts/",
|
||||
# For a test
|
||||
"docs/en/docs/img/favicon.png",
|
||||
]
|
||||
]
|
||||
|
||||
[tool.tiangolo._internal-slim-build.packages.fastapi-slim.project]
|
||||
name = "fastapi-slim"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# For mkdocstrings and tests
|
||||
httpx >=0.23.0,<1.0.0
|
||||
# For linting and generating docs versions
|
||||
ruff ==0.14.3
|
||||
@@ -1,21 +0,0 @@
|
||||
-e .
|
||||
-r requirements-docs-tests.txt
|
||||
mkdocs-material==9.7.0
|
||||
mdx-include >=1.4.1,<2.0.0
|
||||
mkdocs-redirects>=1.2.1,<1.3.0
|
||||
typer == 0.16.0
|
||||
pyyaml >=5.3.1,<7.0.0
|
||||
# For Material for MkDocs, Chinese search
|
||||
jieba==0.42.1
|
||||
# For image processing by Material for MkDocs
|
||||
pillow==11.3.0
|
||||
# For image processing by Material for MkDocs
|
||||
cairosvg==2.8.2
|
||||
mkdocstrings[python]==0.30.1
|
||||
griffe-typingdoc==0.3.0
|
||||
griffe-warnings-deprecated==1.1.0
|
||||
# For griffe, it formats with black
|
||||
black==25.1.0
|
||||
mkdocs-macros-plugin==1.4.1
|
||||
markdown-include-variants==0.0.8
|
||||
python-slugify==8.0.4
|
||||
@@ -1,6 +0,0 @@
|
||||
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,<1.0.0
|
||||
pyyaml >=5.3.1,<7.0.0
|
||||
smokeshow
|
||||
@@ -1,18 +0,0 @@
|
||||
-e .[all]
|
||||
-r requirements-docs-tests.txt
|
||||
pytest >=7.1.3,<9.0.0
|
||||
coverage[toml] >= 6.5.0,< 8.0
|
||||
mypy ==1.14.1
|
||||
dirty-equals ==0.9.0
|
||||
sqlmodel==0.0.27
|
||||
flask >=1.1.2,<4.0.0
|
||||
strawberry-graphql >=0.200.0,< 1.0.0
|
||||
anyio[trio] >=3.2.1,<5.0.0
|
||||
PyJWT==2.9.0
|
||||
pyyaml >=5.3.1,<7.0.0
|
||||
pwdlib[argon2] >=0.2.1
|
||||
inline-snapshot>=0.21.1
|
||||
pytest-codspeed==4.2.0
|
||||
# types
|
||||
types-ujson ==5.10.0.20240515
|
||||
types-orjson ==3.6.2
|
||||
@@ -1,3 +0,0 @@
|
||||
pydantic-ai==0.4.10
|
||||
GitPython==3.1.45
|
||||
pygithub==2.8.1
|
||||
@@ -1,7 +0,0 @@
|
||||
-e .[all]
|
||||
-r requirements-tests.txt
|
||||
-r requirements-docs.txt
|
||||
-r requirements-translations.txt
|
||||
prek==0.2.22
|
||||
# For generating screenshots
|
||||
playwright
|
||||
528
scripts/general-llm-prompt.md
Normal file
528
scripts/general-llm-prompt.md
Normal file
@@ -0,0 +1,528 @@
|
||||
### Your task
|
||||
|
||||
Translate an English original content to a target language.
|
||||
|
||||
The original content is written in Markdown, write the translation in Markdown as well.
|
||||
|
||||
The original content will be surrounded by triple percentage signs (%%%). Do not include the triple percentage signs in the translation.
|
||||
|
||||
### Technical terms in English
|
||||
|
||||
For technical terms in English that don't have a common translation term, use the original term in English.
|
||||
|
||||
### Content of code snippets
|
||||
|
||||
Do not translate the content of code snippets, keep the original in English. For example, `list`, `dict`, keep them as is.
|
||||
|
||||
### Content of code blocks
|
||||
|
||||
Do not translate the content of code blocks, except for comments in the language which the code block uses.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English) - The code block is a bash code example with one comment:
|
||||
|
||||
```bash
|
||||
# Print greeting
|
||||
echo "Hello, World!"
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```bash
|
||||
# Gruß ausgeben
|
||||
echo "Hello, World!"
|
||||
```
|
||||
|
||||
Source (English) - The code block is a console example containing HTML tags. No comments, so nothing to change here:
|
||||
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
|
||||
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
|
||||
Searching for package file structure
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
|
||||
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
|
||||
Searching for package file structure
|
||||
```
|
||||
|
||||
Source (English) - The code block is a console example containing 5 comments:
|
||||
|
||||
|
||||
```console
|
||||
// Go to the home directory
|
||||
$ cd
|
||||
// Create a directory for all your code projects
|
||||
$ mkdir code
|
||||
// Enter into that code directory
|
||||
$ cd code
|
||||
// Create a directory for this project
|
||||
$ mkdir awesome-project
|
||||
// Enter into that project directory
|
||||
$ cd awesome-project
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```console
|
||||
// Gehe zum Home-Verzeichnis
|
||||
$ cd
|
||||
// Erstelle ein Verzeichnis für alle Ihre Code-Projekte
|
||||
$ mkdir code
|
||||
// Gehe in dieses Code-Verzeichnis
|
||||
$ cd code
|
||||
// Erstelle ein Verzeichnis für dieses Projekt
|
||||
$ mkdir awesome-project
|
||||
// Gehe in dieses Projektverzeichnis
|
||||
$ cd awesome-project
|
||||
```
|
||||
|
||||
If there is an existing translation and its Mermaid diagram is in sync with the Mermaid diagram in the English source, except a few translated words, then use the Mermaid diagram of the existing translation. The human editor of the translation translated these words in the Mermaid diagram. Keep these translations, do not revert them back to the English source.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph global[global env]
|
||||
harry-1[harry v1]
|
||||
end
|
||||
subgraph stone-project[philosophers-stone project]
|
||||
stone(philosophers-stone) -->|requires| harry-1
|
||||
end
|
||||
```
|
||||
|
||||
Existing translation (German) - has three translations:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph global[globale Umgebung]
|
||||
harry-1[harry v1]
|
||||
end
|
||||
subgraph stone-project[philosophers-stone-Projekt]
|
||||
stone(philosophers-stone) -->|benötigt| harry-1
|
||||
end
|
||||
```
|
||||
|
||||
Result (German) - you change nothing:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph global[globale Umgebung]
|
||||
harry-1[harry v1]
|
||||
end
|
||||
subgraph stone-project[philosophers-stone-Projekt]
|
||||
stone(philosophers-stone) -->|benötigt| harry-1
|
||||
end
|
||||
```
|
||||
|
||||
### Special blocks
|
||||
|
||||
There are special blocks of notes, tips and others that look like:
|
||||
|
||||
/// note
|
||||
Here goes a note
|
||||
///
|
||||
|
||||
To translate it, keep the same line and add the translation after a vertical bar.
|
||||
|
||||
For example, if you were translating to Spanish, you would write:
|
||||
|
||||
/// note | Nota
|
||||
|
||||
Some examples in Spanish:
|
||||
|
||||
Source (English):
|
||||
|
||||
/// tip
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
/// tip | Consejo
|
||||
|
||||
Source (English):
|
||||
|
||||
/// details | Preview
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
/// details | Vista previa
|
||||
|
||||
### Tab blocks
|
||||
|
||||
There are special blocks surrounded by four slashes (////). They mark text, which will be rendered as part of a tab in the final document. The scheme is:
|
||||
|
||||
//// tab | {tab title}
|
||||
{tab content, may span many lines}
|
||||
////
|
||||
|
||||
Keep everything before the vertical bar (|) as is, including the vertical bar. Translate the tab title. Translate the tab content, applying the rules you know. Keep the four block closing slashes as is.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
Hello
|
||||
////
|
||||
|
||||
Result (German):
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
Hallo
|
||||
////
|
||||
|
||||
Source (English) - Here there is nothing to translate in the tab title:
|
||||
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
Hello again
|
||||
////
|
||||
|
||||
Result (German):
|
||||
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
Hallo wieder
|
||||
////
|
||||
|
||||
### Headings
|
||||
|
||||
Every Markdown heading in the English text (all levels) ends with a part inside curly brackets. This part denotes the hash of this heading, which is used in links to this heading. In translations, translate the heading, but do not translate this hash part, so that links do not break.
|
||||
|
||||
Examples of how to translate a heading:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
## Alternative API docs { #alternative-api-docs }
|
||||
```
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
```
|
||||
## Documentación de la API alternativa { #alternative-api-docs }
|
||||
```
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
### Example { #example }
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
### Beispiel { #example }
|
||||
```
|
||||
|
||||
### Links
|
||||
|
||||
Use the following rules for links (apply both to Markdown-style links ([text](url)) and to HTML-style <a href="url">text</a> tags):
|
||||
|
||||
- For relative URLs, only translate the link text. Do not translate the URL or its parts.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
[One of the fastest Python frameworks available](#performance)
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
[Eines der schnellsten verfügbaren Python-Frameworks](#performance)
|
||||
```
|
||||
|
||||
- For absolute URLs which DO NOT start EXACTLY with https://fastapi.tiangolo.com, only translate the link text and leave the URL unchanged.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel docs</a>
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel-Dokumentation</a>
|
||||
```
|
||||
|
||||
- For absolute URLs which DO start EXACTLY with https://fastapi.tiangolo.com, only translate the link text and change the URL by adding the language code (https://fastapi.tiangolo.com/{language_code}[rest part of the url]).
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<a href="https://fastapi.tiangolo.com/tutorial/path-params/#documentation" class="external-link" target="_blank">Documentation</a>
|
||||
```
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
```
|
||||
<a href="https://fastapi.tiangolo.com/es/tutorial/path-params/#documentation" class="external-link" target="_blank">Documentación</a>
|
||||
```
|
||||
|
||||
- Do not add language codes for URLs that point to static assets (e.g., images, CSS, JavaScript).
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<a href="https://fastapi.tiangolo.com/img/something.jpg" class="external-link" target="_blank">Something</a>
|
||||
```
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
```
|
||||
<a href="https://fastapi.tiangolo.com/img/something.jpg" class="external-link" target="_blank">Algo</a>
|
||||
```
|
||||
|
||||
- For internal links, only translate link text.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
[Create Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
[Pull Requests erzeugen](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}
|
||||
```
|
||||
|
||||
- Do not translate anchor fragments in links (the part after `#`), as they must remain the same to work correctly.
|
||||
|
||||
- If an existing translation has a link with an anchor fragment different to the anchor fragment in the English source, then this is an error. Fix this by using the anchor fragment of the English source.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}
|
||||
```
|
||||
|
||||
Existing wrong translation (German) - notice the wrongly translated anchor fragment:
|
||||
|
||||
```
|
||||
[Body - Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#einzelne-werte-im-body){.internal-link target=_blank}.
|
||||
```
|
||||
|
||||
Result (German) - you fix the anchor fragment:
|
||||
|
||||
```
|
||||
[Body - Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
|
||||
```
|
||||
|
||||
- Do not add anchor fragments at will, even if this makes sense. If the English source has no anchor, don't add one.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
Create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}
|
||||
```
|
||||
|
||||
Wrong translation in German - Anchor added to the URL.
|
||||
|
||||
```
|
||||
Erstelle eine [virtuelle Umgebung](../virtual-environments.md#create-a-virtual-environment){.internal-link target=_blank}
|
||||
```
|
||||
|
||||
Good translation (German) - URL stays like in the English source.
|
||||
|
||||
```
|
||||
Erstelle eine [Virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}
|
||||
```
|
||||
|
||||
### HTML abbr elements
|
||||
|
||||
Translate HTML abbr elements (`<abbr title="description">text</abbr>`) as follows:
|
||||
|
||||
- If the text surrounded by the abbr element is an abbreviation (the text may be surrounded by further HTML or Markdown markup or quotes, for example <code>text</code> or `text` or "text", ignore that further markup when deciding if the text is an abbreviation), and if the description (the text inside the title attribute) contains the full phrase for this abbreviation, then append a dash (-) to the full phrase, followed by the translation of the full phrase.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="{full phrase}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
<abbr title="{full phrase} - {translation of full phrase}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="Internet of Things">IoT</abbr>
|
||||
<abbr title="Central Processing Unit">CPU</abbr>
|
||||
<abbr title="too long; didn't read"><strong>TL;DR:</strong></abbr>
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
<abbr title="Internet of Things - Internet der Dinge">IoT</abbr>
|
||||
<abbr title="Central Processing Unit - Zentrale Verarbeitungseinheit">CPU</abbr>
|
||||
<abbr title="too long; didn't read - zu lang; hab's nicht gelesen"><strong>TL;DR:</strong></abbr>
|
||||
```
|
||||
|
||||
- If the language to which you translate mostly uses the letters of the ASCII char set (for example Spanish, French, German, but not Russian, Chinese) and if the translation of the full phrase is identical to, or starts with the same letters as the original full phrase, then only give the translation of the full phrase.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="{full phrase}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
<abbr title="{translation of full phrase}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="JSON Web Tokens">JWT</abbr>
|
||||
<abbr title="Enumeration">Enum</abbr>
|
||||
<abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
<abbr title="JSON Web Tokens">JWT</abbr>
|
||||
<abbr title="Enumeration">Enum</abbr>
|
||||
<abbr title="Asynchrones Server-Gateway-Interface">ASGI</abbr>
|
||||
```
|
||||
|
||||
- If the description is not a full phrase for an abbreviation which the abbr element surrounds, but some other information, then just translate the description.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="{description}">{text}</abbr>
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
<abbr title="{translation of description}">{translation of text}</abbr>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="also known as: endpoints, routes">path</abbr>
|
||||
<abbr title="a program that checks for code errors">linter</abbr>
|
||||
<abbr title="converting the string that comes from an HTTP request into Python data">parsing</abbr>
|
||||
<abbr title="before 2023-03">0.95.0</abbr>
|
||||
<abbr title="2023-08-26">at the time of writing this</abbr>
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
<abbr title="auch bekannt als: Endpunkte, Routen">Pfad</abbr>
|
||||
<abbr title="Programm das auf Fehler im Code prüft">Linter</abbr>
|
||||
<abbr title="Konvertieren des Strings eines HTTP-Requests in Python-Daten">Parsen</abbr>
|
||||
<abbr title="vor 2023-03">0.95.0</abbr>
|
||||
<abbr title="2023-08-26">zum Zeitpunkt als das hier geschrieben wurde</abbr>
|
||||
```
|
||||
|
||||
- If the text surrounded by the abbr element is an abbreviation and the description contains both the full phrase for that abbreviation, and other information, separated by a colon (`:`), then append a dash (`-`) and the translation of the full phrase to the original full phrase and translate the other information.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="{full phrase}: {other information}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
<abbr title="{full phrase} - {translation of full phrase}: {translation of other information}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="Input/Output: disk reading or writing, network communication.">I/O</abbr>
|
||||
<abbr title="Content Delivery Network: service, that provides static files.">CDN</abbr>
|
||||
<abbr title="Integrated Development Environment: similar to a code editor">IDE</abbr>
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
<abbr title="Input/Output - Eingabe/Ausgabe: Lesen oder Schreiben auf der Festplatte, Netzwerkkommunikation.">I/O</abbr>
|
||||
<abbr title="Content Delivery Network - Inhalte auslieferndes Netzwerk: Dienst, der statische Dateien bereitstellt.">CDN</abbr>
|
||||
<abbr title="Integrated Development Environment - Integrierte Entwicklungsumgebung: Ähnlich einem Code-Editor">IDE</abbr>
|
||||
```
|
||||
|
||||
- You can leave the original full phrase away, if the translated full phrase is identical or starts with the same letters as the original full phrase.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="{full phrase}: {information}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
<abbr title="{translation of full phrase}: {translation of information}">{abbreviation}</abbr>
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
```
|
||||
<abbr title="Object Relational Mapper: a fancy term for a library where some classes represent SQL tables and instances represent rows in those tables">ORM</abbr>
|
||||
```
|
||||
|
||||
Result (German):
|
||||
|
||||
```
|
||||
<abbr title="Objektrelationaler Mapper: Ein Fachbegriff für eine Bibliothek, in der einige Klassen SQL-Tabellen und Instanzen Zeilen in diesen Tabellen darstellen">ORM</abbr>
|
||||
```
|
||||
|
||||
- If there is an existing translation, and it has ADDITIONAL abbr elements in a sentence, and these additional abbr elements do not exist in the related sentence in the English text, then KEEP those additional abbr elements in the translation. Do not remove them. Except when you remove the whole sentence from the translation, because the whole sentence was removed from the English text, then also remove the abbr element. The reasoning for this rule is, that such additional abbr elements are manually added by the human editor of the translation, in order to translate or explain an English word to the human readers of the translation. These additional abbr elements would not make sense in the English text, but they do make sense in the translation. So keep them in the translation, even though they are not part of the English text. This rule only applies to abbr elements.
|
||||
|
||||
- Apply above rules also when there is an existing translation! Make sure that all title attributes in abbr elements get properly translated or updated, using the schemes given above. However, leave the ADDITIONAL abbr's described above alone. Do not change their formatting or content.
|
||||
@@ -25,650 +25,8 @@ non_translated_sections = (
|
||||
"contributing.md",
|
||||
)
|
||||
|
||||
|
||||
general_prompt = """
|
||||
### About literal text in this prompt
|
||||
|
||||
1) In the following instructions (after I say: `The above rules are in effect now`) the two characters `«` and `»` will be used to surround LITERAL TEXT, which is text or characters you shall interpret literally. The `«` and the `»` are not part of the literal text, they are the meta characters denoting it.
|
||||
|
||||
2) Furthermore, text surrounded by `«««` and `»»»` is a BLOCK OF LITERAL TEXT which spans multiple lines. To get its content, dedent all lines of the block until the `«««` and `»»»` are at column zero, then remove the newline (`\n`) after the `«««` and the newline before the `»»»`. The `«««` and the `»»»` are not part of the literal text block, they are the meta characters denoting it.
|
||||
|
||||
3) If you see backticks or any other quotes inside literal text – inside `«` and `»` – or inside blocks of literal text – inside `«««` and `»»»` – then interpret them as literal characters, do NOT interpret them as meta characters.
|
||||
|
||||
The above rules are in effect now.
|
||||
|
||||
|
||||
### Definitions of terms used in this prompt
|
||||
|
||||
"backtick"
|
||||
|
||||
The character «`»
|
||||
Unicode U+0060 (GRAVE ACCENT)
|
||||
|
||||
"single backtick"
|
||||
|
||||
A single backtick – «`»
|
||||
|
||||
"triple backticks"
|
||||
|
||||
Three backticks in a row – «```»
|
||||
|
||||
"neutral double quote"
|
||||
|
||||
The character «"»
|
||||
Unicode U+0022 (QUOTATION MARK)
|
||||
|
||||
"neutral single quote"
|
||||
|
||||
The character «'»
|
||||
Unicode U+0027 (APOSTROPHE)
|
||||
|
||||
"English double typographic quotes"
|
||||
|
||||
The characters «“» and «”»
|
||||
Unicode U+201C (LEFT DOUBLE QUOTATION MARK) and Unicode U+201D (RIGHT DOUBLE QUOTATION MARK)
|
||||
|
||||
"English single typographic quotes"
|
||||
|
||||
The characters «‘» and «’»
|
||||
Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and Unicode U+2019 (RIGHT SINGLE QUOTATION MARK)
|
||||
|
||||
"code snippet"
|
||||
|
||||
Also called "inline code". Text in a Markdown document which is surrounded by single backticks. A paragraph in a Markdown document can have a more than one code snippet.
|
||||
|
||||
Example:
|
||||
|
||||
«««
|
||||
`i am a code snippet`
|
||||
»»»
|
||||
|
||||
Example:
|
||||
|
||||
«««
|
||||
`first code snippet` `second code snippet` `third code snippet`
|
||||
»»»
|
||||
|
||||
"code block"
|
||||
|
||||
Text in a Markdown document which is surrounded by triple backticks. Spreads multiple lines.
|
||||
|
||||
Example:
|
||||
|
||||
«««
|
||||
```
|
||||
Hello
|
||||
World
|
||||
```
|
||||
»»»
|
||||
|
||||
Example:
|
||||
|
||||
«««
|
||||
```python
|
||||
print("hello World")
|
||||
```
|
||||
»»»
|
||||
|
||||
"HTML element"
|
||||
|
||||
a HTML opening tag – e.g. «<div>» – and a HTML closing tag – e.g. «</div>» – surrounding text or other HTML elements.
|
||||
|
||||
|
||||
### Your task
|
||||
|
||||
Translate an English text – the original content – to a target language.
|
||||
|
||||
The original content is written in Markdown, write the translation in Markdown as well.
|
||||
|
||||
The original content will be surrounded by triple percentage signs («%%%»). Do not include the triple percentage signs in the translation.
|
||||
|
||||
|
||||
### Technical terms in English
|
||||
|
||||
For technical terms in English that don't have a common translation term, use the original term in English.
|
||||
|
||||
|
||||
### Content of code snippets
|
||||
|
||||
Do not translate the content of code snippets, keep the original in English. For example, «`list`», «`dict`», keep them as is.
|
||||
|
||||
|
||||
### Content of code blocks
|
||||
|
||||
Do not translate the content of code blocks, except for comments in the language which the code block uses.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English) – The code block is a bash code example with one comment:
|
||||
|
||||
«««
|
||||
```bash
|
||||
# Print greeting
|
||||
echo "Hello, World!"
|
||||
```
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
```bash
|
||||
# Gruß ausgeben
|
||||
echo "Hello, World!"
|
||||
```
|
||||
»»»
|
||||
|
||||
Source (English) – The code block is a console example containing HTML tags. No comments, so nothing to change here:
|
||||
|
||||
«««
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
|
||||
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
|
||||
Searching for package file structure
|
||||
```
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
|
||||
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
|
||||
Searching for package file structure
|
||||
```
|
||||
»»»
|
||||
|
||||
Source (English) – The code block is a console example containing 5 comments:
|
||||
|
||||
«««
|
||||
```console
|
||||
// Go to the home directory
|
||||
$ cd
|
||||
// Create a directory for all your code projects
|
||||
$ mkdir code
|
||||
// Enter into that code directory
|
||||
$ cd code
|
||||
// Create a directory for this project
|
||||
$ mkdir awesome-project
|
||||
// Enter into that project directory
|
||||
$ cd awesome-project
|
||||
```
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
```console
|
||||
// Gehe zum Home-Verzeichnis
|
||||
$ cd
|
||||
// Erstelle ein Verzeichnis für alle Ihre Code-Projekte
|
||||
$ mkdir code
|
||||
// Gehe in dieses Code-Verzeichnis
|
||||
$ cd code
|
||||
// Erstelle ein Verzeichnis für dieses Projekt
|
||||
$ mkdir awesome-project
|
||||
// Gehe in dieses Projektverzeichnis
|
||||
$ cd awesome-project
|
||||
```
|
||||
»»»
|
||||
|
||||
If there is an existing translation and its Mermaid diagram is in sync with the Mermaid diagram in the English source, except a few translated words, then use the Mermaid diagram of the existing translation. The human editor of the translation translated these words in the Mermaid diagram. Keep these translations, do not revert them back to the English source.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph global[global env]
|
||||
harry-1[harry v1]
|
||||
end
|
||||
subgraph stone-project[philosophers-stone project]
|
||||
stone(philosophers-stone) -->|requires| harry-1
|
||||
end
|
||||
```
|
||||
»»»
|
||||
|
||||
Existing translation (German) – has three translations:
|
||||
|
||||
«««
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph global[globale Umgebung]
|
||||
harry-1[harry v1]
|
||||
end
|
||||
subgraph stone-project[philosophers-stone-Projekt]
|
||||
stone(philosophers-stone) -->|benötigt| harry-1
|
||||
end
|
||||
```
|
||||
»»»
|
||||
|
||||
Result (German) – you change nothing:
|
||||
|
||||
«««
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph global[globale Umgebung]
|
||||
harry-1[harry v1]
|
||||
end
|
||||
subgraph stone-project[philosophers-stone-Projekt]
|
||||
stone(philosophers-stone) -->|benötigt| harry-1
|
||||
end
|
||||
```
|
||||
»»»
|
||||
|
||||
|
||||
### Special blocks
|
||||
|
||||
There are special blocks of notes, tips and others that look like:
|
||||
|
||||
«««
|
||||
/// note
|
||||
»»»
|
||||
|
||||
To translate it, keep the same line and add the translation after a vertical bar.
|
||||
|
||||
For example, if you were translating to Spanish, you would write:
|
||||
|
||||
«««
|
||||
/// note | Nota
|
||||
»»»
|
||||
|
||||
Some examples in Spanish:
|
||||
|
||||
Source:
|
||||
|
||||
«««
|
||||
/// tip
|
||||
»»»
|
||||
|
||||
Result:
|
||||
|
||||
«««
|
||||
/// tip | Consejo
|
||||
»»»
|
||||
|
||||
Source:
|
||||
|
||||
«««
|
||||
/// details | Preview
|
||||
»»»
|
||||
|
||||
Result:
|
||||
|
||||
«««
|
||||
/// details | Vista previa
|
||||
»»»
|
||||
|
||||
|
||||
### Tab blocks
|
||||
|
||||
There are special blocks surrounded by four slashes («////»). They mark text, which will be rendered as part of a tab in the final document. The scheme is:
|
||||
|
||||
//// tab | {tab title}
|
||||
{tab content, may span many lines}
|
||||
////
|
||||
|
||||
Keep everything before the vertical bar («|») as is, including the vertical bar. Translate the tab title. Translate the tab content, applying the rules you know. Keep the four block closing slashes as is.
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
Hello
|
||||
////
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
Hallo
|
||||
////
|
||||
»»»
|
||||
|
||||
Source (English) – Here there is nothing to translate in the tab title:
|
||||
|
||||
«««
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
Hello again
|
||||
////
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
Hallo wieder
|
||||
////
|
||||
»»»
|
||||
|
||||
|
||||
### Headings
|
||||
|
||||
Every Markdown heading in the English text (all levels) ends with a part inside curly brackets. This part denotes the hash of this heading, which is used in links to this heading. In translations, translate the heading, but do not translate this hash part, so that links do not break.
|
||||
|
||||
Examples of how to translate a heading:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
## Alternative API docs { #alternative-api-docs }
|
||||
»»»
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
«««
|
||||
## Documentación de la API alternativa { #alternative-api-docs }
|
||||
»»»
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
### Example { #example }
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
### Beispiel { #example }
|
||||
»»»
|
||||
|
||||
|
||||
### Links
|
||||
|
||||
Use the following rules for links (apply both to Markdown-style links ([text](url)) and to HTML-style <a> tags):
|
||||
|
||||
1) For relative URLs, only translate link text. Do not translate the URL or its parts
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
[One of the fastest Python frameworks available](#performance)
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
[Eines der schnellsten verfügbaren Python-Frameworks](#performance)
|
||||
»»»
|
||||
|
||||
2) For absolute URLs which DO NOT start EXACTLY with «https://fastapi.tiangolo.com», only translate link text and leave the URL unchanged.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel docs</a>
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel-Dokumentation</a>
|
||||
»»»
|
||||
|
||||
3) For absolute URLs which DO start EXACTLY with «https://fastapi.tiangolo.com», only translate link text and change the URL by adding language code («https://fastapi.tiangolo.com/{language_code}[rest part of the url]»).
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<a href="https://fastapi.tiangolo.com/tutorial/path-params/#documentation" class="external-link" target="_blank">Documentation</a>
|
||||
»»»
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
«««
|
||||
<a href="https://fastapi.tiangolo.com/es/tutorial/path-params/#documentation" class="external-link" target="_blank">Documentación</a>
|
||||
»»»
|
||||
|
||||
3.1) Do not add language codes for URLs that point to static assets (e.g., images, CSS, JavaScript).
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<a href="https://fastapi.tiangolo.com/img/something.jpg" class="external-link" target="_blank">Something</a>
|
||||
»»»
|
||||
|
||||
Result (Spanish):
|
||||
|
||||
«««
|
||||
<a href="https://fastapi.tiangolo.com/img/something.jpg" class="external-link" target="_blank">Algo</a>
|
||||
»»»
|
||||
|
||||
4) For internal links, only translate link text.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
[Create Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
[Pull Requests erzeugen](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}
|
||||
»»»
|
||||
|
||||
5) Do not translate anchor fragments in links (the part after «#»), as they must remain the same to work correctly.
|
||||
|
||||
5.1) If an existing translation has a link with an anchor fragment different to the anchor fragment in the English source, then this is an error. Fix this by using the anchor fragment of the English source.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}
|
||||
»»»
|
||||
|
||||
Existing wrong translation (German) – notice the wrongly translated anchor fragment:
|
||||
|
||||
«««
|
||||
[Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#einzelne-werte-im-body){.internal-link target=_blank}.
|
||||
»»»
|
||||
|
||||
Result (German) – you fix the anchor fragment:
|
||||
|
||||
«««
|
||||
[Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
|
||||
»»»
|
||||
|
||||
5.2) Do not add anchor fragments at will, even if this makes sense. If the English source has no anchor, don't add one.
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
Create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}
|
||||
»»»
|
||||
|
||||
Wrong translation (German) – Anchor added to the URL.
|
||||
|
||||
«««
|
||||
Erstelle eine [virtuelle Umgebung](../virtual-environments.md#create-a-virtual-environment){.internal-link target=_blank}
|
||||
»»»
|
||||
|
||||
Good translation (German) – URL stays like in the English source.
|
||||
|
||||
«««
|
||||
Erstelle eine [Virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}
|
||||
»»»
|
||||
|
||||
|
||||
### HTML abbr elements
|
||||
|
||||
Translate HTML abbr elements («<abbr title="description">text</abbr>») as follows:
|
||||
|
||||
1) If the text surrounded by the abbr element is an abbreviation (the text may be surrounded by further HTML or Markdown markup or quotes, for example «<code>text</code>» or «`text`» or «"text"», ignore that further markup when deciding if the text is an abbreviation), and if the description (the text inside the title attribute) contains the full phrase for this abbreviation, then append a dash («–») to the full phrase, followed by the translation of the full phrase.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
<abbr title="{full phrase}">{abbreviation}</abbr>
|
||||
|
||||
Result:
|
||||
|
||||
<abbr title="{full phrase} – {translation of full phrase}">{abbreviation}</abbr>
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<abbr title="Internet of Things">IoT</abbr>
|
||||
<abbr title="Central Processing Unit">CPU</abbr>
|
||||
<abbr title="too long; didn't read"><strong>TL;DR:</strong></abbr>
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
<abbr title="Internet of Things – Internet der Dinge">IoT</abbr>
|
||||
<abbr title="Central Processing Unit – Zentrale Verarbeitungseinheit">CPU</abbr>
|
||||
<abbr title="too long; didn't read – zu lang; hab's nicht gelesen"><strong>TL;DR:</strong></abbr>
|
||||
»»»
|
||||
|
||||
1.1) If the language to which you translate mostly uses the letters of the ASCII char set (for example Spanish, French, German, but not Russian, Chinese) and if the translation of the full phrase is identical to, or starts with the same letters as the original full phrase, then only give the translation of the full phrase.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
<abbr title="{full phrase}">{abbreviation}</abbr>
|
||||
|
||||
Result:
|
||||
|
||||
<abbr title="{translation of full phrase}">{abbreviation}</abbr>
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<abbr title="JSON Web Tokens">JWT</abbr>
|
||||
<abbr title="Enumeration">Enum</abbr>
|
||||
<abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
<abbr title="JSON Web Tokens">JWT</abbr>
|
||||
<abbr title="Enumeration">Enum</abbr>
|
||||
<abbr title="Asynchrones Server-Gateway-Interface">ASGI</abbr>
|
||||
»»»
|
||||
|
||||
2) If the description is not a full phrase for an abbreviation which the abbr element surrounds, but some other information, then just translate the description.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
<abbr title="{description}">{text}</abbr>
|
||||
|
||||
Result:
|
||||
|
||||
<abbr title="{translation of description}">{translation of text}</abbr>
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<abbr title="also known as: endpoints, routes">path</abbr>
|
||||
<abbr title="a program that checks for code errors">linter</abbr>
|
||||
<abbr title="converting the string that comes from an HTTP request into Python data">parsing</abbr>
|
||||
<abbr title="before 2023-03">0.95.0</abbr>
|
||||
<abbr title="2023-08-26">at the time of writing this</abbr>
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
<abbr title="auch bekannt als: Endpunkte, Routen">Pfad</abbr>
|
||||
<abbr title="Programm das auf Fehler im Code prüft">Linter</abbr>
|
||||
<abbr title="Konvertieren des Strings eines HTTP-Requests in Python-Daten">Parsen</abbr>
|
||||
<abbr title="vor 2023-03">0.95.0</abbr>
|
||||
<abbr title="2023-08-26">zum Zeitpunkt als das hier geschrieben wurde</abbr>
|
||||
»»»
|
||||
|
||||
|
||||
3) If the text surrounded by the abbr element is an abbreviation and the description contains both the full phrase for that abbreviation, and other information, separated by a colon («:»), then append a dash («–») and the translation of the full phrase to the original full phrase and translate the other information.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
<abbr title="{full phrase}: {other information}">{abbreviation}</abbr>
|
||||
|
||||
Result:
|
||||
|
||||
<abbr title="{full phrase} – {translation of full phrase}: {translation of other information}">{abbreviation}</abbr>
|
||||
|
||||
Examples:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<abbr title="Input/Output: disk reading or writing, network communication.">I/O</abbr>
|
||||
<abbr title="Content Delivery Network: service, that provides static files.">CDN</abbr>
|
||||
<abbr title="Integrated Development Environment: similar to a code editor">IDE</abbr>
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
<abbr title="Input/Output – Eingabe/Ausgabe: Lesen oder Schreiben auf der Festplatte, Netzwerkkommunikation.">I/O</abbr>
|
||||
<abbr title="Content Delivery Network – Inhalte auslieferndes Netzwerk: Dienst, der statische Dateien bereitstellt.">CDN</abbr>
|
||||
<abbr title="Integrated Development Environment – Integrierte Entwicklungsumgebung: Ähnlich einem Code-Editor">IDE</abbr>
|
||||
»»»
|
||||
|
||||
3.1) Like in rule 2.1, you can leave the original full phrase away, if the translated full phrase is identical or starts with the same letters as the original full phrase.
|
||||
|
||||
Conversion scheme:
|
||||
|
||||
Source (English):
|
||||
|
||||
<abbr title="{full phrase}: {information}">{abbreviation}</abbr>
|
||||
|
||||
Result:
|
||||
|
||||
<abbr title="{translation of full phrase}: {translation of information}">{abbreviation}</abbr>
|
||||
|
||||
Example:
|
||||
|
||||
Source (English):
|
||||
|
||||
«««
|
||||
<abbr title="Object Relational Mapper: a fancy term for a library where some classes represent SQL tables and instances represent rows in those tables">ORM</abbr>
|
||||
»»»
|
||||
|
||||
Result (German):
|
||||
|
||||
«««
|
||||
<abbr title="Objektrelationaler Mapper: Ein Fachbegriff für eine Bibliothek, in der einige Klassen SQL-Tabellen und Instanzen Zeilen in diesen Tabellen darstellen">ORM</abbr>
|
||||
»»»
|
||||
|
||||
4) If there is an existing translation, and it has ADDITIONAL abbr elements in a sentence, and these additional abbr elements do not exist in the related sentence in the English text, then KEEP those additional abbr elements in the translation. Do not remove them. Except when you remove the whole sentence from the translation, because the whole sentence was removed from the English text, then also remove the abbr element. The reasoning for this rule is, that such additional abbr elements are manually added by the human editor of the translation, in order to translate or explain an English word to the human readers of the translation. These additional abbr elements would not make sense in the English text, but they do make sense in the translation. So keep them in the translation, even though they are not part of the English text. This rule only applies to abbr elements.
|
||||
|
||||
5) Apply above rules also when there is an existing translation! Make sure that all title attributes in abbr elements get properly translated or updated, using the schemes given above. However, leave the ADDITIONAL abbr's from rule 4 alone. Do not change their formatting or content.
|
||||
|
||||
"""
|
||||
general_prompt_path = Path(__file__).absolute().parent / "llm-general-prompt.md"
|
||||
general_prompt = general_prompt_path.read_text(encoding="utf-8")
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
@@ -1036,9 +394,13 @@ def make_pr(
|
||||
print("Creating PR")
|
||||
g = Github(github_token)
|
||||
gh_repo = g.get_repo(github_repository)
|
||||
pr = gh_repo.create_pull(
|
||||
title=message, body=message, base="master", head=branch_name
|
||||
body = (
|
||||
message
|
||||
+ "\n\nThis PR was created automatically using LLMs."
|
||||
+ f"\n\nIt uses the prompt file https://github.com/fastapi/fastapi/blob/master/docs/{language}/llm-prompt.md."
|
||||
+ "\n\nIn most cases, it's better to make PRs updating that file so that the LLM can do a better job generating the translations than suggesting changes in this PR."
|
||||
)
|
||||
pr = gh_repo.create_pull(title=message, body=body, base="master", head=branch_name)
|
||||
print(f"Created PR: {pr.number}")
|
||||
print("Finished")
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Union
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
@@ -52,19 +51,13 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/Foo"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Foo",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"$ref": "#/components/schemas/Foo"}
|
||||
)
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/Foo"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Foo",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
from pydantic import BaseModel, HttpUrl
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
@@ -32,121 +32,114 @@ client = TestClient(app)
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/": {
|
||||
"post": {
|
||||
"summary": "Main Route",
|
||||
"operationId": "main_route__post",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"title": "Callback Url",
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
}
|
||||
)
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
| IsDict(
|
||||
{
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/": {
|
||||
"post": {
|
||||
"summary": "Main Route",
|
||||
"operationId": "main_route__post",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {
|
||||
"title": "Callback Url",
|
||||
"maxLength": 2083,
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
}
|
||||
),
|
||||
"name": "callback_url",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"name": "callback_url",
|
||||
"in": "query",
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
"callbacks": {
|
||||
"callback_route": {
|
||||
"{$callback_url}/callback/": {
|
||||
"get": {
|
||||
"summary": "Callback Route",
|
||||
"operationId": "callback_route__callback_url__callback__get",
|
||||
"responses": {
|
||||
"400": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CustomModel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Bad Request",
|
||||
},
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {"schema": {}}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"CustomModel": {
|
||||
"title": "CustomModel",
|
||||
"required": ["a"],
|
||||
"type": "object",
|
||||
"properties": {"a": {"title": "A", "type": "integer"}},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError"
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"callbacks": {
|
||||
"callback_route": {
|
||||
"{$callback_url}/callback/": {
|
||||
"get": {
|
||||
"summary": "Callback Route",
|
||||
"operationId": "callback_route__callback_url__callback__get",
|
||||
"responses": {
|
||||
"400": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CustomModel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Bad Request",
|
||||
},
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {"schema": {}}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"CustomModel": {
|
||||
"title": "CustomModel",
|
||||
"required": ["a"],
|
||||
"type": "object",
|
||||
"properties": {"a": {"title": "A", "type": "integer"}},
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import APIRouter, FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -32,44 +31,23 @@ client = TestClient(app)
|
||||
|
||||
foo_is_missing = {
|
||||
"detail": [
|
||||
IsDict(
|
||||
{
|
||||
"loc": ["query", "foo"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
"input": None,
|
||||
}
|
||||
)
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
| IsDict(
|
||||
{
|
||||
"loc": ["query", "foo"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
)
|
||||
{
|
||||
"loc": ["query", "foo"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
foo_is_short = {
|
||||
"detail": [
|
||||
IsDict(
|
||||
{
|
||||
"ctx": {"min_length": 1},
|
||||
"loc": ["query", "foo"],
|
||||
"msg": "String should have at least 1 character",
|
||||
"type": "string_too_short",
|
||||
"input": "",
|
||||
}
|
||||
)
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
| IsDict(
|
||||
{
|
||||
"ctx": {"limit_value": 1},
|
||||
"loc": ["query", "foo"],
|
||||
"msg": "ensure this value has at least 1 characters",
|
||||
"type": "value_error.any_str.min_length",
|
||||
}
|
||||
)
|
||||
{
|
||||
"ctx": {"min_length": 1},
|
||||
"loc": ["query", "foo"],
|
||||
"msg": "String should have at least 1 character",
|
||||
"type": "string_too_short",
|
||||
"input": "",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from .main import app
|
||||
@@ -274,14 +273,10 @@ def test_openapi_schema():
|
||||
"name": "item_id",
|
||||
"in": "path",
|
||||
"required": True,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Item Id",
|
||||
}
|
||||
)
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
| IsDict({"title": "Item Id", "type": "string"}),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Item Id",
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
@@ -984,14 +979,10 @@ def test_openapi_schema():
|
||||
"name": "query",
|
||||
"in": "query",
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"title": "Query",
|
||||
}
|
||||
)
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
| IsDict({"title": "Query", "type": "integer"}),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"title": "Query",
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
@@ -46,29 +45,16 @@ async def no_duplicates_sub(
|
||||
def test_no_duplicates_invalid():
|
||||
response = client.post("/no-duplicates", json={"item": {"data": "myitem"}})
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "item2"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "item2"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "item2"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_no_duplicates():
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import APIRouter, Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -54,29 +53,16 @@ async def overrider_dependency_with_sub(msg: dict = Depends(overrider_sub_depend
|
||||
def test_main_depends():
|
||||
response = client.get("/main-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_main_depends_q_foo():
|
||||
@@ -100,29 +86,16 @@ def test_main_depends_q_foo_skip_100_limit_200():
|
||||
def test_decorator_depends():
|
||||
response = client.get("/decorator-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_decorator_depends_q_foo():
|
||||
@@ -140,29 +113,16 @@ def test_decorator_depends_q_foo_skip_100_limit_200():
|
||||
def test_router_depends():
|
||||
response = client.get("/router-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_router_depends_q_foo():
|
||||
@@ -186,29 +146,16 @@ def test_router_depends_q_foo_skip_100_limit_200():
|
||||
def test_router_decorator_depends():
|
||||
response = client.get("/router-decorator-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_router_decorator_depends_q_foo():
|
||||
@@ -272,29 +219,17 @@ def test_override_with_sub_main_depends():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/main-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -302,29 +237,17 @@ def test_override_with_sub__main_depends_q_foo():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/main-depends/?q=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -340,29 +263,17 @@ def test_override_with_sub_decorator_depends():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/decorator-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -370,29 +281,17 @@ def test_override_with_sub_decorator_depends_q_foo():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/decorator-depends/?q=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -408,29 +307,17 @@ def test_override_with_sub_router_depends():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/router-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -438,29 +325,17 @@ def test_override_with_sub_router_depends_q_foo():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/router-depends/?q=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -476,29 +351,17 @@ def test_override_with_sub_router_decorator_depends():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/router-decorator-depends/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
@@ -506,29 +369,17 @@ def test_override_with_sub_router_decorator_depends_q_foo():
|
||||
app.dependency_overrides[common_parameters] = overrider_dependency_with_sub
|
||||
response = client.get("/router-decorator-depends/?q=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "k"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "k"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
app.dependency_overrides = {}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -328,14 +327,10 @@ def test_openapi_schema():
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": IsDict(
|
||||
{
|
||||
"title": "Price",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
| IsDict({"title": "Price", "type": "number"}),
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import HasRepr, IsDict, IsOneOf
|
||||
from dirty_equals import HasRepr
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.exceptions import ResponseValidationError
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -63,23 +63,13 @@ def test_validator_is_cloned(client: TestClient):
|
||||
with pytest.raises(ResponseValidationError) as err:
|
||||
client.get("/model/modelX")
|
||||
assert err.value.errors() == [
|
||||
IsDict(
|
||||
{
|
||||
"type": "value_error",
|
||||
"loc": ("response", "name"),
|
||||
"msg": "Value error, name must end in A",
|
||||
"input": "modelX",
|
||||
"ctx": {"error": HasRepr("ValueError('name must end in A')")},
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
{
|
||||
"loc": ("response", "name"),
|
||||
"msg": "name must end in A",
|
||||
"type": "value_error",
|
||||
}
|
||||
)
|
||||
{
|
||||
"type": "value_error",
|
||||
"loc": ("response", "name"),
|
||||
"msg": "Value error, name must end in A",
|
||||
"input": "modelX",
|
||||
"ctx": {"error": HasRepr("ValueError('name must end in A')")},
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -145,23 +135,14 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
"ModelA": {
|
||||
"title": "ModelA",
|
||||
"required": IsOneOf(
|
||||
["name", "description", "foo"],
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
["name", "foo"],
|
||||
),
|
||||
"required": ["name", "foo"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": IsDict(
|
||||
{
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
|
|
||||
# TODO remove when deprecating Pydantic v1
|
||||
IsDict({"title": "Description", "type": "string"}),
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"foo": {"$ref": "#/components/schemas/ModelB"},
|
||||
"tags": {
|
||||
"additionalProperties": {"type": "string"},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -79,68 +78,37 @@ def test_invalid_data():
|
||||
},
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["body", "age"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "seventy",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "age"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["body", "age"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "seventy",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_no_data():
|
||||
response = client.post("/form/")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": {"tags": ["foo", "bar"], "with": "nothing"},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "lastname"],
|
||||
"msg": "Field required",
|
||||
"input": {"tags": ["foo", "bar"], "with": "nothing"},
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "username"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "lastname"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": {"tags": ["foo", "bar"], "with": "nothing"},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "lastname"],
|
||||
"msg": "Field required",
|
||||
"input": {"tags": ["foo", "bar"], "with": "nothing"},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_extra_param_single():
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -163,16 +162,10 @@ def test_openapi_schema():
|
||||
"required": False,
|
||||
"name": "user_id",
|
||||
"in": "query",
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "User Id", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
},
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -208,16 +201,10 @@ def test_openapi_schema():
|
||||
"required": False,
|
||||
"name": "user_id",
|
||||
"in": "query",
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "User Id", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
@@ -247,16 +234,10 @@ def test_openapi_schema():
|
||||
"required": True,
|
||||
"name": "user_id",
|
||||
"in": "path",
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "User Id", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
},
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -292,16 +273,10 @@ def test_openapi_schema():
|
||||
"required": True,
|
||||
"name": "user_id",
|
||||
"in": "path",
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "User Id", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "User Id",
|
||||
},
|
||||
},
|
||||
],
|
||||
"responses": {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
from pydantic import BaseModel, condecimal
|
||||
|
||||
app = FastAPI()
|
||||
@@ -24,109 +25,65 @@ client = TestClient(app)
|
||||
def test_put_correct_body():
|
||||
response = client.post("/items/", json=[{"name": "Foo", "age": 5}])
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"item": [
|
||||
{
|
||||
"name": "Foo",
|
||||
"age": IsOneOf(
|
||||
5,
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"5",
|
||||
),
|
||||
}
|
||||
]
|
||||
}
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"item": [
|
||||
{
|
||||
"name": "Foo",
|
||||
"age": "5",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_jsonable_encoder_requiring_error():
|
||||
response = client.post("/items/", json=[{"name": "Foo", "age": -1.0}])
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "greater_than",
|
||||
"loc": ["body", 0, "age"],
|
||||
"msg": "Input should be greater than 0",
|
||||
"input": -1.0,
|
||||
"ctx": {"gt": 0},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"ctx": {"limit_value": 0.0},
|
||||
"loc": ["body", 0, "age"],
|
||||
"msg": "ensure this value is greater than 0",
|
||||
"type": "value_error.number.not_gt",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "greater_than",
|
||||
"loc": ["body", 0, "age"],
|
||||
"msg": "Input should be greater than 0",
|
||||
"input": -1.0,
|
||||
"ctx": {"gt": 0},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_incorrect_body_multiple():
|
||||
response = client.post("/items/", json=[{"age": "five"}, {"age": "six"}])
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", 0, "name"],
|
||||
"msg": "Field required",
|
||||
"input": {"age": "five"},
|
||||
},
|
||||
{
|
||||
"type": "decimal_parsing",
|
||||
"loc": ["body", 0, "age"],
|
||||
"msg": "Input should be a valid decimal",
|
||||
"input": "five",
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", 1, "name"],
|
||||
"msg": "Field required",
|
||||
"input": {"age": "six"},
|
||||
},
|
||||
{
|
||||
"type": "decimal_parsing",
|
||||
"loc": ["body", 1, "age"],
|
||||
"msg": "Input should be a valid decimal",
|
||||
"input": "six",
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", 0, "name"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", 0, "age"],
|
||||
"msg": "value is not a valid decimal",
|
||||
"type": "type_error.decimal",
|
||||
},
|
||||
{
|
||||
"loc": ["body", 1, "name"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", 1, "age"],
|
||||
"msg": "value is not a valid decimal",
|
||||
"type": "type_error.decimal",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", 0, "name"],
|
||||
"msg": "Field required",
|
||||
"input": {"age": "five"},
|
||||
},
|
||||
{
|
||||
"type": "decimal_parsing",
|
||||
"loc": ["body", 0, "age"],
|
||||
"msg": "Input should be a valid decimal",
|
||||
"input": "five",
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", 1, "name"],
|
||||
"msg": "Field required",
|
||||
"input": {"age": "six"},
|
||||
},
|
||||
{
|
||||
"type": "decimal_parsing",
|
||||
"loc": ["body", 1, "age"],
|
||||
"msg": "Input should be a valid decimal",
|
||||
"input": "six",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
@@ -179,31 +136,21 @@ def test_openapi_schema():
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"age": IsDict(
|
||||
{
|
||||
"title": "Age",
|
||||
"anyOf": [
|
||||
{"exclusiveMinimum": 0.0, "type": "number"},
|
||||
IsOneOf(
|
||||
# pydantic < 2.12.0
|
||||
{"type": "string"},
|
||||
# pydantic >= 2.12.0
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": r"^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$",
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Age",
|
||||
"exclusiveMinimum": 0.0,
|
||||
"type": "number",
|
||||
}
|
||||
),
|
||||
"age": {
|
||||
"title": "Age",
|
||||
"anyOf": [
|
||||
{"exclusiveMinimum": 0.0, "type": "number"},
|
||||
IsOneOf(
|
||||
# pydantic < 2.12.0
|
||||
{"type": "string"},
|
||||
# pydantic >= 2.12.0
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": r"^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$",
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -22,40 +21,22 @@ def test_multi_query():
|
||||
def test_multi_query_incorrect():
|
||||
response = client.get("/items/?q=five&q=six")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "q", 0],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "five",
|
||||
},
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "q", 1],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "six",
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "q", 0],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
},
|
||||
{
|
||||
"loc": ["query", "q", 1],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "q", 0],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "five",
|
||||
},
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "q", 1],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "six",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema():
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Union
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
@@ -155,26 +154,12 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{"data": "Data in Body examples, example1"}
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"allOf": [
|
||||
{"$ref": "#/components/schemas/Item"}
|
||||
],
|
||||
"title": "Item",
|
||||
"examples": [
|
||||
{"data": "Data in Body examples, example1"}
|
||||
],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{"data": "Data in Body examples, example1"}
|
||||
],
|
||||
},
|
||||
"examples": {
|
||||
"Example One": {
|
||||
"summary": "Example One Summary",
|
||||
@@ -265,27 +250,14 @@ def test_openapi_schema():
|
||||
"name": "data",
|
||||
"in": "query",
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"examples": [
|
||||
"json_schema_query1",
|
||||
"json_schema_query2",
|
||||
],
|
||||
"title": "Data",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"examples": [
|
||||
"json_schema_query1",
|
||||
"json_schema_query2",
|
||||
],
|
||||
"type": "string",
|
||||
"title": "Data",
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"examples": [
|
||||
"json_schema_query1",
|
||||
"json_schema_query2",
|
||||
],
|
||||
"title": "Data",
|
||||
},
|
||||
"examples": {
|
||||
"Query One": {
|
||||
"summary": "Query One Summary",
|
||||
@@ -323,27 +295,14 @@ def test_openapi_schema():
|
||||
"name": "data",
|
||||
"in": "header",
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"examples": [
|
||||
"json_schema_header1",
|
||||
"json_schema_header2",
|
||||
],
|
||||
"title": "Data",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"json_schema_header1",
|
||||
"json_schema_header2",
|
||||
],
|
||||
"title": "Data",
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"examples": [
|
||||
"json_schema_header1",
|
||||
"json_schema_header2",
|
||||
],
|
||||
"title": "Data",
|
||||
},
|
||||
"examples": {
|
||||
"Header One": {
|
||||
"summary": "Header One Summary",
|
||||
@@ -381,27 +340,14 @@ def test_openapi_schema():
|
||||
"name": "data",
|
||||
"in": "cookie",
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"examples": [
|
||||
"json_schema_cookie1",
|
||||
"json_schema_cookie2",
|
||||
],
|
||||
"title": "Data",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"json_schema_cookie1",
|
||||
"json_schema_cookie2",
|
||||
],
|
||||
"title": "Data",
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"examples": [
|
||||
"json_schema_cookie1",
|
||||
"json_schema_cookie2",
|
||||
],
|
||||
"title": "Data",
|
||||
},
|
||||
"examples": {
|
||||
"Cookie One": {
|
||||
"summary": "Cookie One Summary",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -53,21 +52,11 @@ def test_openapi():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"default": 50,
|
||||
"title": "Standard Query Param",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Standard Query Param",
|
||||
"type": "integer",
|
||||
"default": 50,
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"default": 50,
|
||||
"title": "Standard Query Param",
|
||||
},
|
||||
"name": "standard_query_param",
|
||||
"in": "query",
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
|
||||
app = FastAPI(
|
||||
servers=[
|
||||
@@ -30,39 +30,31 @@ def test_app():
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"servers": [
|
||||
{"url": "/", "description": "Default, relative server"},
|
||||
{
|
||||
"url": IsOneOf(
|
||||
"http://staging.localhost.tiangolo.com:8000/",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"http://staging.localhost.tiangolo.com:8000",
|
||||
),
|
||||
"description": "Staging but actually localhost still",
|
||||
},
|
||||
{
|
||||
"url": IsOneOf(
|
||||
"https://prod.example.com/",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"https://prod.example.com",
|
||||
)
|
||||
},
|
||||
],
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"summary": "Foo",
|
||||
"operationId": "foo_foo_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"servers": [
|
||||
{"url": "/", "description": "Default, relative server"},
|
||||
{
|
||||
"url": "http://staging.localhost.tiangolo.com:8000",
|
||||
"description": "Staging but actually localhost still",
|
||||
},
|
||||
{"url": "https://prod.example.com"},
|
||||
],
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"summary": "Foo",
|
||||
"operationId": "foo_foo_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Any
|
||||
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi.params import Body, Cookie, Header, Param, Path, Query
|
||||
|
||||
test_data: list[Any] = ["teststr", None, ..., 1, []]
|
||||
@@ -19,11 +18,7 @@ def test_param_repr_none():
|
||||
|
||||
|
||||
def test_param_repr_ellipsis():
|
||||
assert repr(Param(...)) == IsOneOf(
|
||||
"Param(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Param(Ellipsis)",
|
||||
)
|
||||
assert repr(Param(...)) == "Param(PydanticUndefined)"
|
||||
|
||||
|
||||
def test_param_repr_number():
|
||||
@@ -35,16 +30,8 @@ def test_param_repr_list():
|
||||
|
||||
|
||||
def test_path_repr():
|
||||
assert repr(Path()) == IsOneOf(
|
||||
"Path(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Path(Ellipsis)",
|
||||
)
|
||||
assert repr(Path(...)) == IsOneOf(
|
||||
"Path(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Path(Ellipsis)",
|
||||
)
|
||||
assert repr(Path()) == "Path(PydanticUndefined)"
|
||||
assert repr(Path(...)) == "Path(PydanticUndefined)"
|
||||
|
||||
|
||||
def test_query_repr_str():
|
||||
@@ -56,11 +43,7 @@ def test_query_repr_none():
|
||||
|
||||
|
||||
def test_query_repr_ellipsis():
|
||||
assert repr(Query(...)) == IsOneOf(
|
||||
"Query(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Query(Ellipsis)",
|
||||
)
|
||||
assert repr(Query(...)) == "Query(PydanticUndefined)"
|
||||
|
||||
|
||||
def test_query_repr_number():
|
||||
@@ -80,11 +63,7 @@ def test_header_repr_none():
|
||||
|
||||
|
||||
def test_header_repr_ellipsis():
|
||||
assert repr(Header(...)) == IsOneOf(
|
||||
"Header(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Header(Ellipsis)",
|
||||
)
|
||||
assert repr(Header(...)) == "Header(PydanticUndefined)"
|
||||
|
||||
|
||||
def test_header_repr_number():
|
||||
@@ -104,11 +83,7 @@ def test_cookie_repr_none():
|
||||
|
||||
|
||||
def test_cookie_repr_ellipsis():
|
||||
assert repr(Cookie(...)) == IsOneOf(
|
||||
"Cookie(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Cookie(Ellipsis)",
|
||||
)
|
||||
assert repr(Cookie(...)) == "Cookie(PydanticUndefined)"
|
||||
|
||||
|
||||
def test_cookie_repr_number():
|
||||
@@ -128,11 +103,7 @@ def test_body_repr_none():
|
||||
|
||||
|
||||
def test_body_repr_ellipsis():
|
||||
assert repr(Body(...)) == IsOneOf(
|
||||
"Body(PydanticUndefined)",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"Body(Ellipsis)",
|
||||
)
|
||||
assert repr(Body(...)) == "Body(PydanticUndefined)"
|
||||
|
||||
|
||||
def test_body_repr_number():
|
||||
|
||||
1182
tests/test_path.py
1182
tests/test_path.py
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from .main import app
|
||||
@@ -9,29 +8,16 @@ client = TestClient(app)
|
||||
def test_query():
|
||||
response = client.get("/query")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_query_baz():
|
||||
@@ -43,29 +29,16 @@ def test_query_query_baz():
|
||||
def test_query_not_declared_baz():
|
||||
response = client.get("/query?not_declared=baz")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_optional():
|
||||
@@ -89,29 +62,16 @@ def test_query_optional_not_declared_baz():
|
||||
def test_query_int():
|
||||
response = client.get("/query/int")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_int_query_42():
|
||||
@@ -123,85 +83,46 @@ def test_query_int_query_42():
|
||||
def test_query_int_query_42_5():
|
||||
response = client.get("/query/int?query=42.5")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "42.5",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "42.5",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_int_query_baz():
|
||||
response = client.get("/query/int?query=baz")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "baz",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "baz",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_int_not_declared_baz():
|
||||
response = client.get("/query/int?not_declared=baz")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_int_optional():
|
||||
@@ -219,29 +140,16 @@ def test_query_int_optional_query_50():
|
||||
def test_query_int_optional_query_foo():
|
||||
response = client.get("/query/int/optional?query=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_int_default():
|
||||
@@ -259,29 +167,16 @@ def test_query_int_default_query_50():
|
||||
def test_query_int_default_query_foo():
|
||||
response = client.get("/query/int/default?query=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_param():
|
||||
@@ -299,29 +194,16 @@ def test_query_param_query_50():
|
||||
def test_query_param_required():
|
||||
response = client.get("/query/param-required")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_param_required_query_50():
|
||||
@@ -333,29 +215,16 @@ def test_query_param_required_query_50():
|
||||
def test_query_param_required_int():
|
||||
response = client.get("/query/param-required/int")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_param_required_int_query_50():
|
||||
@@ -367,29 +236,16 @@ def test_query_param_required_int_query_50():
|
||||
def test_query_param_required_int_query_foo():
|
||||
response = client.get("/query/param-required/int?query=foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "query"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["query", "query"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_query_frozenset_query_1_query_1_query_2():
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.exceptions import FastAPIDeprecationWarning
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
|
||||
from .utils import needs_py310
|
||||
|
||||
@@ -47,31 +47,17 @@ def test_query_nonregexquery():
|
||||
client = get_client()
|
||||
response = client.post("/items/", data={"q": "nonregexquery"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "q"],
|
||||
"msg": "String should match pattern '^fixedquery$'",
|
||||
"input": "nonregexquery",
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
"loc": ["body", "q"],
|
||||
"msg": 'string does not match regex "^fixedquery$"',
|
||||
"type": "value_error.str.regex",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "q"],
|
||||
"msg": "String should match pattern '^fixedquery$'",
|
||||
"input": "nonregexquery",
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@needs_py310
|
||||
@@ -79,104 +65,88 @@ def test_openapi_schema():
|
||||
client = get_client()
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
# insert_assert(response.json())
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"post": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Body_read_items_items__post"
|
||||
}
|
||||
],
|
||||
"title": "Body",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"post": {
|
||||
"summary": "Read Items",
|
||||
"operationId": "read_items_items__post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Body_read_items_items__post"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_read_items_items__post": {
|
||||
"properties": {
|
||||
"q": IsDict(
|
||||
{
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Body_read_items_items__post": {
|
||||
"properties": {
|
||||
"q": {
|
||||
"anyOf": [
|
||||
{"type": "string", "pattern": "^fixedquery$"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"type": "string", "pattern": "^fixedquery$", "title": "Q"}
|
||||
)
|
||||
},
|
||||
"type": "object",
|
||||
"title": "Body_read_items_items__post",
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
"type": "array",
|
||||
"title": "Detail",
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Location",
|
||||
},
|
||||
"msg": {"type": "string", "title": "Message"},
|
||||
"type": {"type": "string", "title": "Error Type"},
|
||||
"type": "object",
|
||||
"title": "Body_read_items_items__post",
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"title": "ValidationError",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Detail",
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [{"type": "string"}, {"type": "integer"}]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Location",
|
||||
},
|
||||
"msg": {"type": "string", "title": "Message"},
|
||||
"type": {"type": "string", "title": "Error Type"},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"title": "ValidationError",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.exceptions import FastAPIDeprecationWarning
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -47,31 +46,17 @@ def test_query_params_str_validations_item_query_nonregexquery():
|
||||
client = get_client()
|
||||
response = client.get("/items/", params={"q": "nonregexquery"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should match pattern '^fixedquery$'",
|
||||
"input": "nonregexquery",
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
"loc": ["query", "q"],
|
||||
"msg": 'string does not match regex "^fixedquery$"',
|
||||
"type": "value_error.str.regex",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["query", "q"],
|
||||
"msg": "String should match pattern '^fixedquery$'",
|
||||
"input": "nonregexquery",
|
||||
"ctx": {"pattern": "^fixedquery$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@needs_py310
|
||||
@@ -93,23 +78,13 @@ def test_openapi_schema():
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"type": "string", "pattern": "^fixedquery$"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^fixedquery$",
|
||||
"title": "Q",
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"type": "string", "pattern": "^fixedquery$"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Q",
|
||||
},
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated, Union
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf, IsPartialDict
|
||||
from dirty_equals import IsOneOf, IsPartialDict
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -59,28 +59,16 @@ def test_required_list_str_missing(path: str, json: Union[dict, None]):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body", "p"], ["body"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": IsOneOf(["body", "p"], ["body"]),
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body", "p"], ["body"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -148,29 +136,16 @@ def test_required_list_alias_missing(path: str, json: Union[dict, None]):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -181,29 +156,16 @@ def test_required_list_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json={"p": ["hello", "world"]})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": ["hello", "world"]}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": ["hello", "world"]}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -38,30 +37,19 @@ def test_optional_list_str_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p": {"items": {"type": "string"}, "type": "array", "title": "P"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_list_str_missing():
|
||||
@@ -75,29 +63,16 @@ def test_model_optional_list_str_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-list-str")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -153,34 +128,19 @@ def test_optional_list_str_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Alias",
|
||||
},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_list_alias_missing():
|
||||
@@ -194,29 +154,16 @@ def test_model_optional_list_alias_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-list-alias")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -289,34 +236,19 @@ def test_optional_list_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_list_validation_alias_missing():
|
||||
@@ -330,29 +262,16 @@ def test_model_optional_list_validation_alias_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-list-validation-alias")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -438,34 +357,19 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_list_alias_and_validation_alias_missing():
|
||||
@@ -479,29 +383,16 @@ def test_model_optional_list_alias_and_validation_alias_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-list-alias-and-validation-alias")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -36,27 +35,16 @@ def test_optional_str_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p": {"type": "string", "title": "P"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_str_missing():
|
||||
@@ -70,29 +58,16 @@ def test_model_optional_str_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-str")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -148,27 +123,16 @@ def test_optional_str_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {"type": "string", "title": "P Alias"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_alias_missing():
|
||||
@@ -182,29 +146,16 @@ def test_model_optional_alias_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-alias")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -274,27 +225,16 @@ def test_optional_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {"type": "string", "title": "P Val Alias"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_validation_alias_missing():
|
||||
@@ -308,29 +248,16 @@ def test_model_optional_validation_alias_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-validation-alias")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -413,27 +340,16 @@ def test_optional_alias_and_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {"type": "string", "title": "P Val Alias"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
def test_optional_alias_and_validation_alias_missing():
|
||||
@@ -447,29 +363,16 @@ def test_model_optional_alias_and_validation_alias_missing():
|
||||
client = TestClient(app)
|
||||
response = client.post("/model-optional-alias-and-validation-alias")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"input": None,
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"type": "missing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated, Any, Union
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -55,29 +55,16 @@ def test_required_str_missing(path: str, json: Union[dict[str, Any], None]):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body"], ["body", "p"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": IsOneOf(["body"], ["body", "p"]),
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body"], ["body", "p"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -141,29 +128,16 @@ def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -174,29 +148,16 @@ def test_required_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json={"p": "hello"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": "hello"}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": IsOneOf(["body", "p_alias"], ["body"]),
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": "hello"}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Cookie, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -32,26 +31,15 @@ async def read_model_optional_str(p: Annotated[CookieModelOptionalStr, Cookie()]
|
||||
)
|
||||
def test_optional_str_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "cookie",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "P", "type": "string"},
|
||||
"name": "p",
|
||||
"in": "cookie",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "cookie",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -104,26 +92,15 @@ async def read_model_optional_alias(p: Annotated[CookieModelOptionalAlias, Cooki
|
||||
)
|
||||
def test_optional_str_alias_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "cookie",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "P Alias", "type": "string"},
|
||||
"name": "p_alias",
|
||||
"in": "cookie",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "cookie",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import Cookie, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -49,29 +49,16 @@ def test_required_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["cookie", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["cookie", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["cookie", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -127,29 +114,16 @@ def test_required_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["cookie", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["cookie", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["cookie", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -164,32 +138,19 @@ def test_required_alias_by_name(path: str):
|
||||
client.cookies.set("p", "hello")
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["cookie", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(
|
||||
None,
|
||||
{"p": "hello"},
|
||||
),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["cookie", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["cookie", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(
|
||||
None,
|
||||
{"p": "hello"},
|
||||
),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -36,27 +35,11 @@ def test_list_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
)
|
||||
| IsDict(
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P",
|
||||
},
|
||||
)
|
||||
)
|
||||
"p": {
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P",
|
||||
},
|
||||
},
|
||||
"required": ["p"],
|
||||
"title": body_model_name,
|
||||
@@ -75,29 +58,16 @@ def test_list_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -143,27 +113,11 @@ def test_list_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
)
|
||||
| IsDict(
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P Alias",
|
||||
},
|
||||
)
|
||||
)
|
||||
"p_alias": {
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P Alias",
|
||||
},
|
||||
},
|
||||
"required": ["p_alias"],
|
||||
"title": body_model_name,
|
||||
@@ -182,29 +136,16 @@ def test_list_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -218,29 +159,16 @@ def test_list_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, files=[("p", b"hello"), ("p", b"world")])
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -291,27 +219,11 @@ def test_list_validation_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
)
|
||||
| IsDict(
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
)
|
||||
)
|
||||
"p_val_alias": {
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
},
|
||||
"required": ["p_val_alias"],
|
||||
"title": body_model_name,
|
||||
@@ -424,27 +336,11 @@ def test_list_alias_and_validation_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
)
|
||||
| IsDict(
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
)
|
||||
)
|
||||
"p_val_alias": {
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
},
|
||||
"required": ["p_val_alias"],
|
||||
"title": body_model_name,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -36,21 +35,13 @@ def test_optional_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "P", "type": "string", "format": "binary"}
|
||||
)
|
||||
),
|
||||
"p": {
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
@@ -116,21 +107,13 @@ def test_optional_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "P Alias", "type": "string", "format": "binary"}
|
||||
)
|
||||
),
|
||||
"p_alias": {
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
@@ -215,21 +198,13 @@ def test_optional_validation_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "P Val Alias", "type": "string", "format": "binary"}
|
||||
)
|
||||
),
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
@@ -319,21 +294,13 @@ def test_optional_alias_and_validation_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": (
|
||||
IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "P Val Alias", "type": "string", "format": "binary"}
|
||||
)
|
||||
),
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"type": "string", "format": "binary"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -38,28 +37,16 @@ def test_optional_list_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": (
|
||||
IsDict(
|
||||
"p": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "P",
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
)
|
||||
),
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
@@ -125,28 +112,16 @@ def test_optional_list_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": (
|
||||
IsDict(
|
||||
"p_alias": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "P Alias",
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
}
|
||||
)
|
||||
),
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
@@ -228,28 +203,16 @@ def test_optional_validation_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": (
|
||||
IsDict(
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "P Val Alias",
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
}
|
||||
)
|
||||
),
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
@@ -336,28 +299,16 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": (
|
||||
IsDict(
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "P Val Alias",
|
||||
"type": "array",
|
||||
"items": {"type": "string", "format": "binary"},
|
||||
}
|
||||
)
|
||||
),
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
}
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -55,29 +54,16 @@ def test_required_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -142,29 +128,16 @@ def test_required_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -178,29 +151,16 @@ def test_required_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, files=[("p", b"hello")])
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf, IsPartialDict
|
||||
from dirty_equals import IsOneOf, IsPartialDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -58,28 +58,16 @@ def test_required_list_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -146,29 +134,16 @@ def test_required_list_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -182,29 +157,16 @@ def test_required_list_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, data={"p": ["hello", "world"]})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": ["hello", "world"]}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": ["hello", "world"]}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -38,30 +37,19 @@ def test_optional_list_str_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p": {"items": {"type": "string"}, "type": "array", "title": "P"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -119,34 +107,19 @@ def test_optional_list_str_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Alias",
|
||||
},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -217,34 +190,19 @@ def test_optional_list_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -326,34 +284,19 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -36,27 +35,16 @@ def test_optional_str_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p": {"type": "string", "title": "P"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -112,27 +100,16 @@ def test_optional_str_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_alias": {"type": "string", "title": "P Alias"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -200,27 +177,16 @@ def test_optional_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {"type": "string", "title": "P Val Alias"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -303,27 +269,16 @@ def test_optional_alias_and_validation_alias_schema(path: str):
|
||||
openapi = app.openapi()
|
||||
body_model_name = get_body_model_name(openapi, path)
|
||||
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == IsDict(
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
assert app.openapi()["components"]["schemas"][body_model_name] == {
|
||||
"properties": {
|
||||
"p_val_alias": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Val Alias",
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"properties": {
|
||||
"p_val_alias": {"type": "string", "title": "P Val Alias"},
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
)
|
||||
},
|
||||
"title": body_model_name,
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -54,29 +54,16 @@ def test_required_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -137,29 +124,16 @@ def test_required_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -170,29 +144,16 @@ def test_required_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, data={"p": "hello"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": "hello"}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": "hello"}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import AnyThing, IsDict, IsOneOf, IsPartialDict
|
||||
from dirty_equals import AnyThing, IsOneOf, IsPartialDict
|
||||
from fastapi import FastAPI, Header
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -53,28 +53,16 @@ def test_required_list_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -135,29 +123,16 @@ def test_required_list_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -171,29 +146,16 @@ def test_required_list_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path, headers=[("p", "hello"), ("p", "world")])
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, IsPartialDict({"p": ["hello", "world"]})),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, IsPartialDict({"p": ["hello", "world"]})),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Header
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -36,29 +35,18 @@ async def read_model_optional_list_str(
|
||||
)
|
||||
def test_optional_list_str_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"items": {"type": "string"}, "type": "array", "title": "P"},
|
||||
"name": "p",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "header",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -112,33 +100,18 @@ async def read_model_optional_list_alias(
|
||||
)
|
||||
def test_optional_list_str_alias_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "header",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Header
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -32,26 +31,15 @@ async def read_model_optional_str(p: Annotated[HeaderModelOptionalStr, Header()]
|
||||
)
|
||||
def test_optional_str_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "P", "type": "string"},
|
||||
"name": "p",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "header",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -103,26 +91,15 @@ async def read_model_optional_alias(p: Annotated[HeaderModelOptionalAlias, Heade
|
||||
)
|
||||
def test_optional_str_alias_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "P Alias", "type": "string"},
|
||||
"name": "p_alias",
|
||||
"in": "header",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "header",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import AnyThing, IsDict, IsOneOf, IsPartialDict
|
||||
from dirty_equals import AnyThing, IsOneOf, IsPartialDict
|
||||
from fastapi import FastAPI, Header
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -49,29 +49,16 @@ def test_required_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -126,29 +113,16 @@ def test_required_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": AnyThing,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -162,29 +136,16 @@ def test_required_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path, headers={"p": "hello"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, IsPartialDict({"p": "hello"})),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, IsPartialDict({"p": "hello"})),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -53,28 +53,16 @@ def test_required_list_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -135,29 +123,16 @@ def test_required_list_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -171,29 +146,16 @@ def test_required_list_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(f"{path}?p=hello&p=world")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": ["hello", "world"]}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {"p": ["hello", "world"]}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -36,29 +35,18 @@ async def read_model_optional_list_str(
|
||||
)
|
||||
def test_optional_list_str_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"items": {"type": "string"}, "type": "array", "title": "P"},
|
||||
"name": "p",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "query",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -112,33 +100,18 @@ async def read_model_optional_list_alias(
|
||||
)
|
||||
def test_optional_list_str_alias_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"items": {"type": "string"},
|
||||
"type": "array",
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"items": {"type": "string"}, "type": "array"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "query",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -32,26 +31,15 @@ async def read_model_optional_str(p: Annotated[QueryModelOptionalStr, Query()]):
|
||||
)
|
||||
def test_optional_str_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "P", "type": "string"},
|
||||
"name": "p",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P",
|
||||
},
|
||||
"name": "p",
|
||||
"in": "query",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -103,26 +91,15 @@ async def read_model_optional_alias(p: Annotated[QueryModelOptionalAlias, Query(
|
||||
)
|
||||
def test_optional_str_alias_schema(path: str):
|
||||
assert app.openapi()["paths"][path]["get"]["parameters"] == [
|
||||
IsDict(
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "P Alias", "type": "string"},
|
||||
"name": "p_alias",
|
||||
"in": "query",
|
||||
}
|
||||
)
|
||||
{
|
||||
"required": False,
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "P Alias",
|
||||
},
|
||||
"name": "p_alias",
|
||||
"in": "query",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -49,29 +49,16 @@ def test_required_str_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "p"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -126,29 +113,16 @@ def test_required_alias_missing(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(path)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(None, {}),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -162,32 +136,19 @@ def test_required_alias_by_name(path: str):
|
||||
client = TestClient(app)
|
||||
response = client.get(f"{path}?p=hello")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(
|
||||
None,
|
||||
{"p": "hello"},
|
||||
),
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "p_alias"],
|
||||
"msg": "Field required",
|
||||
"input": IsOneOf(
|
||||
None,
|
||||
{"p": "hello"},
|
||||
),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
|
||||
from fastapi.exceptions import FastAPIDeprecationWarning
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -336,28 +335,13 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{"data": "Data in Body examples, example1"},
|
||||
{"data": "Data in Body examples, example2"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove this when deprecating Pydantic v1
|
||||
{
|
||||
"allOf": [
|
||||
{"$ref": "#/components/schemas/Item"}
|
||||
],
|
||||
"title": "Item",
|
||||
"examples": [
|
||||
{"data": "Data in Body examples, example1"},
|
||||
{"data": "Data in Body examples, example2"},
|
||||
],
|
||||
}
|
||||
)
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{"data": "Data in Body examples, example1"},
|
||||
{"data": "Data in Body examples, example2"},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -387,28 +371,13 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{"data": "examples example_examples 1"},
|
||||
{"data": "examples example_examples 2"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove this when deprecating Pydantic v1
|
||||
{
|
||||
"allOf": [
|
||||
{"$ref": "#/components/schemas/Item"}
|
||||
],
|
||||
"title": "Item",
|
||||
"examples": [
|
||||
{"data": "examples example_examples 1"},
|
||||
{"data": "examples example_examples 2"},
|
||||
],
|
||||
},
|
||||
),
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item",
|
||||
"examples": [
|
||||
{"data": "examples example_examples 1"},
|
||||
{"data": "examples example_examples 2"},
|
||||
],
|
||||
},
|
||||
"example": {"data": "Overridden example"},
|
||||
}
|
||||
},
|
||||
@@ -539,16 +508,10 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{"title": "Data", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
},
|
||||
"example": "query1",
|
||||
"name": "data",
|
||||
"in": "query",
|
||||
@@ -579,21 +542,11 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["query1", "query2"],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{
|
||||
"type": "string",
|
||||
"title": "Data",
|
||||
"examples": ["query1", "query2"],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["query1", "query2"],
|
||||
},
|
||||
"name": "data",
|
||||
"in": "query",
|
||||
}
|
||||
@@ -623,21 +576,11 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["query1", "query2"],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{
|
||||
"type": "string",
|
||||
"title": "Data",
|
||||
"examples": ["query1", "query2"],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["query1", "query2"],
|
||||
},
|
||||
"example": "query_overridden",
|
||||
"name": "data",
|
||||
"in": "query",
|
||||
@@ -668,16 +611,10 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{"title": "Data", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
},
|
||||
"example": "header1",
|
||||
"name": "data",
|
||||
"in": "header",
|
||||
@@ -708,21 +645,11 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["header1", "header2"],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{
|
||||
"type": "string",
|
||||
"title": "Data",
|
||||
"examples": ["header1", "header2"],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["header1", "header2"],
|
||||
},
|
||||
"name": "data",
|
||||
"in": "header",
|
||||
}
|
||||
@@ -752,21 +679,11 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["header1", "header2"],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Data",
|
||||
"type": "string",
|
||||
"examples": ["header1", "header2"],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["header1", "header2"],
|
||||
},
|
||||
"example": "header_overridden",
|
||||
"name": "data",
|
||||
"in": "header",
|
||||
@@ -797,16 +714,10 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{"title": "Data", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
},
|
||||
"example": "cookie1",
|
||||
"name": "data",
|
||||
"in": "cookie",
|
||||
@@ -837,21 +748,11 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["cookie1", "cookie2"],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Data",
|
||||
"type": "string",
|
||||
"examples": ["cookie1", "cookie2"],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["cookie1", "cookie2"],
|
||||
},
|
||||
"name": "data",
|
||||
"in": "cookie",
|
||||
}
|
||||
@@ -881,21 +782,11 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["cookie1", "cookie2"],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: Remove this when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Data",
|
||||
"type": "string",
|
||||
"examples": ["cookie1", "cookie2"],
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Data",
|
||||
"examples": ["cookie1", "cookie2"],
|
||||
},
|
||||
"example": "cookie_overridden",
|
||||
"name": "data",
|
||||
"in": "cookie",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -64,79 +63,43 @@ def test_security_oauth2_password_bearer_no_header():
|
||||
def test_strict_login_no_data():
|
||||
response = client.post("/login")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "password"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "username"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "password"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "password"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_strict_login_no_grant_type():
|
||||
response = client.post("/login", data={"username": "johndoe", "password": "secret"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -153,31 +116,17 @@ def test_strict_login_incorrect_grant_type(grant_type: str):
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": 'string does not match regex "^password$"',
|
||||
"type": "value_error.str.regex",
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_strict_login_correct_grant_type():
|
||||
@@ -264,26 +213,14 @@ def test_openapi_schema():
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"password": {"title": "Password", "type": "string"},
|
||||
"scope": {"title": "Scope", "type": "string", "default": ""},
|
||||
"client_id": IsDict(
|
||||
{
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Client Id", "type": "string"}
|
||||
),
|
||||
"client_secret": IsDict(
|
||||
{
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Client Secret", "type": "string"}
|
||||
),
|
||||
"client_id": {
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"client_secret": {
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -67,79 +66,43 @@ def test_security_oauth2_password_bearer_no_header():
|
||||
def test_strict_login_no_data():
|
||||
response = client.post("/login")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "password"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "username"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "password"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "password"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_strict_login_no_grant_type():
|
||||
response = client.post("/login", data={"username": "johndoe", "password": "secret"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -156,31 +119,17 @@ def test_strict_login_incorrect_grant_type(grant_type: str):
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": 'string does not match regex "^password$"',
|
||||
"type": "value_error.str.regex",
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_strict_login_correct_data():
|
||||
@@ -267,26 +216,14 @@ def test_openapi_schema():
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"password": {"title": "Password", "type": "string"},
|
||||
"scope": {"title": "Scope", "type": "string", "default": ""},
|
||||
"client_id": IsDict(
|
||||
{
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Client Id", "type": "string"}
|
||||
),
|
||||
"client_secret": IsDict(
|
||||
{
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Client Secret", "type": "string"}
|
||||
),
|
||||
"client_id": {
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"client_secret": {
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -68,79 +67,43 @@ def test_security_oauth2_password_bearer_no_header():
|
||||
def test_strict_login_None():
|
||||
response = client.post("/login", data=None)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "password"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "username"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "password"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "username"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "password"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_strict_login_no_grant_type():
|
||||
response = client.post("/login", data={"username": "johndoe", "password": "secret"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -157,31 +120,17 @@ def test_strict_login_incorrect_grant_type(grant_type: str):
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": 'string does not match regex "^password$"',
|
||||
"type": "value_error.str.regex",
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_strict_login_correct_correct_grant_type():
|
||||
@@ -268,26 +217,14 @@ def test_openapi_schema():
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
"password": {"title": "Password", "type": "string"},
|
||||
"scope": {"title": "Scope", "type": "string", "default": ""},
|
||||
"client_id": IsDict(
|
||||
{
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Client Id", "type": "string"}
|
||||
),
|
||||
"client_secret": IsDict(
|
||||
{
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Client Secret", "type": "string"}
|
||||
),
|
||||
"client_id": {
|
||||
"title": "Client Id",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"client_secret": {
|
||||
"title": "Client Secret",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, HttpUrl
|
||||
@@ -99,30 +98,18 @@ def test_openapi_schema():
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"title": "Callback Url",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"minLength": 1,
|
||||
"maxLength": 2083,
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Callback Url",
|
||||
"maxLength": 2083,
|
||||
"minLength": 1,
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
}
|
||||
),
|
||||
"schema": {
|
||||
"title": "Callback Url",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"minLength": 1,
|
||||
"maxLength": 2083,
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
},
|
||||
"name": "callback_url",
|
||||
"in": "query",
|
||||
}
|
||||
@@ -262,16 +249,10 @@ def test_openapi_schema():
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {"title": "Id", "type": "string"},
|
||||
"title": IsDict(
|
||||
{
|
||||
"title": "Title",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Title", "type": "string"}
|
||||
),
|
||||
"title": {
|
||||
"title": "Title",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"customer": {"title": "Customer", "type": "string"},
|
||||
"total": {"title": "Total", "type": "number"},
|
||||
},
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
@@ -125,31 +124,16 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"title": "Square",
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"$ref": "#/components/schemas/Coordinate"},
|
||||
{"$ref": "#/components/schemas/Coordinate"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Square",
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"items": [
|
||||
{"$ref": "#/components/schemas/Coordinate"},
|
||||
{"$ref": "#/components/schemas/Coordinate"},
|
||||
],
|
||||
}
|
||||
)
|
||||
"schema": {
|
||||
"title": "Square",
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"$ref": "#/components/schemas/Coordinate"},
|
||||
{"$ref": "#/components/schemas/Coordinate"},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -212,28 +196,16 @@ def test_openapi_schema():
|
||||
"required": ["values"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": IsDict(
|
||||
{
|
||||
"title": "Values",
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"type": "integer"},
|
||||
{"type": "integer"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Values",
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"items": [{"type": "integer"}, {"type": "integer"}],
|
||||
}
|
||||
)
|
||||
"values": {
|
||||
"title": "Values",
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"type": "integer"},
|
||||
{"type": "integer"},
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
"Coordinate": {
|
||||
@@ -264,26 +236,15 @@ def test_openapi_schema():
|
||||
"items": {
|
||||
"title": "Items",
|
||||
"type": "array",
|
||||
"items": IsDict(
|
||||
{
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"type": "string"},
|
||||
{"type": "string"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"items": [{"type": "string"}, {"type": "string"}],
|
||||
}
|
||||
),
|
||||
"items": {
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
"prefixItems": [
|
||||
{"type": "string"},
|
||||
{"type": "string"},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ import os
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.utils import needs_py310
|
||||
@@ -80,16 +79,10 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
||||
"title": "Img",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Img", "type": "boolean"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
||||
"title": "Img",
|
||||
},
|
||||
"name": "img",
|
||||
"in": "query",
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ import os
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.utils import needs_py310
|
||||
@@ -83,16 +82,10 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
||||
"title": "Img",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Img", "type": "boolean"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
||||
"title": "Img",
|
||||
},
|
||||
"name": "img",
|
||||
"in": "query",
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
|
||||
from docs_src.behind_a_proxy.tutorial003_py39 import app
|
||||
|
||||
@@ -15,40 +15,34 @@ def test_main():
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"servers": [
|
||||
{"url": "/api/v1"},
|
||||
{
|
||||
"url": IsOneOf(
|
||||
"https://stag.example.com/",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"https://stag.example.com",
|
||||
),
|
||||
"description": "Staging environment",
|
||||
},
|
||||
{
|
||||
"url": IsOneOf(
|
||||
"https://prod.example.com/",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"https://prod.example.com",
|
||||
),
|
||||
"description": "Production environment",
|
||||
},
|
||||
],
|
||||
"paths": {
|
||||
"/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"servers": [
|
||||
{"url": "/api/v1"},
|
||||
{
|
||||
"url": "https://stag.example.com",
|
||||
"description": "Staging environment",
|
||||
},
|
||||
{
|
||||
"url": "https://prod.example.com",
|
||||
"description": "Production environment",
|
||||
},
|
||||
],
|
||||
"paths": {
|
||||
"/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
|
||||
from docs_src.behind_a_proxy.tutorial004_py39 import app
|
||||
|
||||
@@ -15,39 +15,33 @@ def test_main():
|
||||
def test_openapi_schema():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"servers": [
|
||||
{
|
||||
"url": IsOneOf(
|
||||
"https://stag.example.com/",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"https://stag.example.com",
|
||||
),
|
||||
"description": "Staging environment",
|
||||
},
|
||||
{
|
||||
"url": IsOneOf(
|
||||
"https://prod.example.com/",
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
"https://prod.example.com",
|
||||
),
|
||||
"description": "Production environment",
|
||||
},
|
||||
],
|
||||
"paths": {
|
||||
"/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
assert response.json() == snapshot(
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://stag.example.com",
|
||||
"description": "Staging environment",
|
||||
},
|
||||
{
|
||||
"url": "https://prod.example.com",
|
||||
"description": "Production environment",
|
||||
},
|
||||
],
|
||||
"paths": {
|
||||
"/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@@ -28,29 +27,16 @@ def test_users_token_jessica(client: TestClient):
|
||||
def test_users_with_no_token(client: TestClient):
|
||||
response = client.get("/users")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_users_foo_token_jessica(client: TestClient):
|
||||
@@ -62,29 +48,16 @@ def test_users_foo_token_jessica(client: TestClient):
|
||||
def test_users_foo_with_no_token(client: TestClient):
|
||||
response = client.get("/users/foo")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_users_me_token_jessica(client: TestClient):
|
||||
@@ -96,29 +69,16 @@ def test_users_me_token_jessica(client: TestClient):
|
||||
def test_users_me_with_no_token(client: TestClient):
|
||||
response = client.get("/users/me")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_users_token_monica_with_no_jessica(client: TestClient):
|
||||
@@ -141,29 +101,16 @@ def test_items_token_jessica(client: TestClient):
|
||||
def test_items_with_no_token_jessica(client: TestClient):
|
||||
response = client.get("/items", headers={"X-Token": "fake-super-secret-token"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_items_plumbus_token_jessica(client: TestClient):
|
||||
@@ -187,29 +134,16 @@ def test_items_plumbus_with_no_token(client: TestClient):
|
||||
"/items/plumbus", headers={"X-Token": "fake-super-secret-token"}
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_items_with_invalid_token(client: TestClient):
|
||||
@@ -227,57 +161,31 @@ def test_items_bar_with_invalid_token(client: TestClient):
|
||||
def test_items_with_missing_x_token_header(client: TestClient):
|
||||
response = client.get("/items?token=jessica")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_items_plumbus_with_missing_x_token_header(client: TestClient):
|
||||
response = client.get("/items/plumbus?token=jessica")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_root_token_jessica(client: TestClient):
|
||||
@@ -289,68 +197,37 @@ def test_root_token_jessica(client: TestClient):
|
||||
def test_root_with_no_token(client: TestClient):
|
||||
response = client.get("/")
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_no_header(client: TestClient):
|
||||
response = client.put("/items/foo")
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["query", "token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["query", "token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["header", "x-token"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_put_invalid_header(client: TestClient):
|
||||
|
||||
@@ -2,7 +2,6 @@ import importlib
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
@@ -74,124 +73,67 @@ def test_post_with_str_float_description_tax(client: TestClient):
|
||||
def test_post_with_only_name(client: TestClient):
|
||||
response = client.post("/items/", json={"name": "Foo"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {"name": "Foo"},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {"name": "Foo"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_post_with_only_name_price(client: TestClient):
|
||||
response = client.post("/items/", json={"name": "Foo", "price": "twenty"})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "float_parsing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Input should be a valid number, unable to parse string as a number",
|
||||
"input": "twenty",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"msg": "value is not a valid float",
|
||||
"type": "type_error.float",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "float_parsing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Input should be a valid number, unable to parse string as a number",
|
||||
"input": "twenty",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_post_with_no_data(client: TestClient):
|
||||
response = client.post("/items/", json={})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "name"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", "name"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
{
|
||||
"loc": ["body", "price"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "name"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body", "price"],
|
||||
"msg": "Field required",
|
||||
"input": {},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_post_with_none(client: TestClient):
|
||||
response = client.post("/items/", json=None)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": ["body"],
|
||||
"msg": "Field required",
|
||||
"input": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_post_broken_body(client: TestClient):
|
||||
@@ -201,67 +143,32 @@ def test_post_broken_body(client: TestClient):
|
||||
content="{some broken json}",
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "json_invalid",
|
||||
"loc": ["body", 1],
|
||||
"msg": "JSON decode error",
|
||||
"input": {},
|
||||
"ctx": {
|
||||
"error": "Expecting property name enclosed in double quotes"
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body", 1],
|
||||
"msg": "Expecting property name enclosed in double quotes: line 1 column 2 (char 1)",
|
||||
"type": "value_error.jsondecode",
|
||||
"ctx": {
|
||||
"msg": "Expecting property name enclosed in double quotes",
|
||||
"doc": "{some broken json}",
|
||||
"pos": 1,
|
||||
"lineno": 1,
|
||||
"colno": 2,
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "json_invalid",
|
||||
"loc": ["body", 1],
|
||||
"msg": "JSON decode error",
|
||||
"input": {},
|
||||
"ctx": {"error": "Expecting property name enclosed in double quotes"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_post_form_for_json(client: TestClient):
|
||||
response = client.post("/items/", data={"name": "Foo", "price": 50.5})
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": "name=Foo&price=50.5",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "value is not a valid dict",
|
||||
"type": "type_error.dict",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": "name=Foo&price=50.5",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_explicit_content_type(client: TestClient):
|
||||
@@ -302,84 +209,46 @@ def test_wrong_headers(client: TestClient):
|
||||
"/items/", content=data, headers={"Content-Type": "text/plain"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": '{"name": "Foo", "price": 50.5}',
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "value is not a valid dict",
|
||||
"type": "type_error.dict",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": '{"name": "Foo", "price": 50.5}',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/items/", content=data, headers={"Content-Type": "application/geo+json-seq"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": '{"name": "Foo", "price": 50.5}',
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "value is not a valid dict",
|
||||
"type": "type_error.dict",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": '{"name": "Foo", "price": 50.5}',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/items/", content=data, headers={"Content-Type": "application/not-really-json"}
|
||||
)
|
||||
assert response.status_code == 422, response.text
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": '{"name": "Foo", "price": 50.5}',
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["body"],
|
||||
"msg": "value is not a valid dict",
|
||||
"type": "type_error.dict",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "model_attributes_type",
|
||||
"loc": ["body"],
|
||||
"msg": "Input should be a valid dictionary or object to extract fields from",
|
||||
"input": '{"name": "Foo", "price": 50.5}',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_other_exceptions(client: TestClient):
|
||||
@@ -435,26 +304,14 @@ def test_openapi_schema(client: TestClient):
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"description": IsDict(
|
||||
{
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Description", "type": "string"}
|
||||
),
|
||||
"tax": IsDict(
|
||||
{
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Tax", "type": "number"}
|
||||
),
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
@@ -59,31 +58,17 @@ def test_items_6(client: TestClient):
|
||||
def test_invalid_price(client: TestClient):
|
||||
response = client.put("/items/5", json={"item": {"name": "Foo", "price": -3.0}})
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "greater_than",
|
||||
"loc": ["body", "item", "price"],
|
||||
"msg": "Input should be greater than 0",
|
||||
"input": -3.0,
|
||||
"ctx": {"gt": 0.0},
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"ctx": {"limit_value": 0},
|
||||
"loc": ["body", "item", "price"],
|
||||
"msg": "ensure this value is greater than 0",
|
||||
"type": "value_error.number.not_gt",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "greater_than",
|
||||
"loc": ["body", "item", "price"],
|
||||
"msg": "Input should be greater than 0",
|
||||
"input": -3.0,
|
||||
"ctx": {"gt": 0.0},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
@@ -142,39 +127,23 @@ def test_openapi_schema(client: TestClient):
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": IsDict(
|
||||
{
|
||||
"title": "The description of the item",
|
||||
"anyOf": [
|
||||
{"maxLength": 300, "type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "The description of the item",
|
||||
"maxLength": 300,
|
||||
"type": "string",
|
||||
}
|
||||
),
|
||||
"description": {
|
||||
"title": "The description of the item",
|
||||
"anyOf": [
|
||||
{"maxLength": 300, "type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"exclusiveMinimum": 0.0,
|
||||
"type": "number",
|
||||
"description": "The price must be greater than zero",
|
||||
},
|
||||
"tax": IsDict(
|
||||
{
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Tax", "type": "number"}
|
||||
),
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Body_update_item_items__item_id__put": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py310
|
||||
@@ -53,29 +52,16 @@ def test_post_no_body(client: TestClient):
|
||||
def test_post_id_foo(client: TestClient):
|
||||
response = client.put("/items/foo", json=None)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["path", "item_id"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
) | IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": ["path", "item_id"],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.json() == {
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": ["path", "item_id"],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_openapi_schema(client: TestClient):
|
||||
@@ -119,16 +105,10 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Q", "type": "string"}
|
||||
),
|
||||
"schema": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Q",
|
||||
},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
@@ -136,19 +116,13 @@ def test_openapi_schema(client: TestClient):
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": IsDict(
|
||||
{
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/Item"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Item",
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"$ref": "#/components/schemas/Item"}
|
||||
)
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"$ref": "#/components/schemas/Item"},
|
||||
{"type": "null"},
|
||||
],
|
||||
"title": "Item",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -163,27 +137,15 @@ def test_openapi_schema(client: TestClient):
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": IsDict(
|
||||
{
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Description", "type": "string"}
|
||||
),
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": IsDict(
|
||||
{
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
}
|
||||
)
|
||||
| IsDict(
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
{"title": "Tax", "type": "number"}
|
||||
),
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user