Skip to content

Commit

Permalink
bugfix
Browse files Browse the repository at this point in the history
- preventing fastapg issue [#4191](tiangolo/fastapi#4191)
- readme update
  • Loading branch information
cercide committed Aug 18, 2022
1 parent ca9288f commit 3ce57ad
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 47 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python package

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:
build:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --ignore=E221,E124,E125,E501,E129 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --ignore=E221,E124,E125,E501,E129 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
39 changes: 39 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Upload Python Package

on:
release:
types: [published]

permissions:
contents: read

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
21 changes: 5 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,10 @@ if __name__ == "__main__":
![Hello World Example](.github/rsc/example.gif)

# Limitations
This package depends on fastapi and xsdata. However, fastapi depends on
pydantic, which ships a [bug](https://github.com/pydantic/pydantic/issues/4353) that causes several side effects.
Among other, this bug is fixed within the major branch. Nevertheless, the bug still occurs in the current version
(1.9.2). Anyhow, this package supports both versions.
- This package depends on fastapi and xsdata. However, fastapi depends on
pydantic, which ships a [bug](https://github.com/pydantic/pydantic/issues/4353) that causes several side effects.
Among other, this bug is fixed within the major branch. Nevertheless, the bug still occurs in the current version
(1.9.2). Anyhow, this package supports both versions.

- :warning: Do not use keyword `required` for a field's metatdata. This will crash the openapi schema generator. Remove
typehint `Optional` instead.

- :warning: You cannot use the same type for the response_model and the body. This will crash the openapi schema
generator. For example, this will not work:

```python
@app.post("/echo", response_model=Echo)
def echo(x: Echo = XmlBody()) -> Echo:
```

Recently, this bug was fixed within pydantic's main branch. However, it still exists in 1.9.2.

typehint `Optional` instead.
17 changes: 16 additions & 1 deletion fastapi_xml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,19 @@
"XmlBody"
]

__version__ = "1.0.0a1"
__version__ = "1.0.0a2"



nonjson.OPENAPI_SCHEMA_MODIFIER.append(xmlbody.add_openapi_xml_schema)

try:
# https://github.com/pydantic/pydantic/issues/4353
from .pydantic_dataclass_patch import pydantic_process_class_patched
except ImportError:
# the patch does not work with the pydantic.dataclasses update (commit 576e4a3a8d9c98cbf5a1fe5149450febef887cc9)
# no worries, that update works as it should and is compatible with fastapi-xml
pass
else:
import pydantic.dataclasses
pydantic.dataclasses._process_class = pydantic_process_class_patched
9 changes: 7 additions & 2 deletions fastapi_xml/pydantic_dataclass_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from pydantic.main import create_model
from pydantic.typing import resolve_annotations
from pydantic.utils import ClassAttribute
from pydantic.dataclasses import _generate_pydantic_post_init, is_builtin_dataclass, _validate_dataclass, _get_validators
from pydantic.dataclasses import _generate_pydantic_post_init, is_builtin_dataclass, _validate_dataclass, _get_validators, setattr_validate_assignment

if TYPE_CHECKING:
from pydantic.dataclasses import Dataclass

_CACHE: Dict[Type, Type['Dataclass']] = {}

def pydantic_process_class_patched(
_cls: Type[Any],
Expand All @@ -22,6 +23,10 @@ def pydantic_process_class_patched(
frozen: bool,
config: Optional[Type[Any]],
) -> Type['Dataclass']:
or_cls = _cls
if or_cls in _CACHE:
return _CACHE[or_cls]

import dataclasses

post_init_original = getattr(_cls, '__post_init__', None)
Expand Down Expand Up @@ -111,5 +116,5 @@ def pydantic_process_class_patched(
cls.__setattr__ = setattr_validate_assignment # type: ignore[assignment]

cls.__pydantic_model__.__try_update_forward_refs__(**{cls.__name__: cls})

_CACHE[or_cls] = cls
return cls
16 changes: 1 addition & 15 deletions fastapi_xml/xmlbody.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,18 +233,4 @@ def add_openapi_xml_schema(
prefix = field.metadata.get("target_namespace"),
attribute = is_attribute,
wrapped = None
)


OPENAPI_SCHEMA_MODIFIER.append(add_openapi_xml_schema)

try:
# https://github.com/pydantic/pydantic/issues/4353
from .pydantic_dataclass_patch import pydantic_process_class_patched
except ImportError:
# the patch does not work with the pydantic.dataclasses update (commit 576e4a3a8d9c98cbf5a1fe5149450febef887cc9)
# no worries, that update works as it should and is compatible with fastapi-xml
pass
else:
import pydantic.dataclasses
pydantic.dataclasses._process_class = pydantic_process_class_patched
)

0 comments on commit 3ce57ad

Please sign in to comment.