pydantic-forms 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.bumpversion.cfg +1 -1
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.github/workflows/run-linting-tests.yml +7 -10
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.github/workflows/run-unit-tests.yml +10 -12
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.pre-commit-config.yaml +6 -8
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/PKG-INFO +5 -5
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/__init__.py +1 -1
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/core/asynchronous.py +1 -1
- pydantic_forms-2.3.0/pydantic_forms/core/shared.py +113 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/core/sync.py +1 -1
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/types.py +3 -8
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/read_only.py +2 -2
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pyproject.toml +18 -13
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/setup.cfg +1 -2
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/helpers.py +1 -1
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_accept.py +0 -2
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_choice_list.py +1 -7
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_constrained_list.py +3 -13
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_display_subscription.py +1 -7
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_list_of_two.py +4 -11
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_migration_summary.py +1 -7
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_read_only_field.py +3 -5
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_shared.py +1 -3
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_utils_from_serializable.py +0 -1
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_utils_to_serializable.py +4 -3
- pydantic_forms-2.2.0/pydantic_forms/core/shared.py +0 -91
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.coveragerc +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.github/dependabot.yml +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.github/workflows/publish-release.yaml +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.gitignore +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/.stignore +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/LICENSE +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/README.md +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/codecov.yml +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/core/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/core/translations.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/exception_handlers/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/exception_handlers/fastapi.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/exceptions.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/py.typed +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/utils/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/utils/json.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/utils/schema.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/accept.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/callout.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/choice.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/choice_list.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/contact_person.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/contact_person_list.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/display_subscription.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/divider.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/hidden.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/label.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/list_of_one.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/list_of_two.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/long_text.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/migration_summary.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/organisation_id.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/timestamp.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/unique_constrained_list.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/helpers.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/setup.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/exception_handlers/__init__.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/exception_handlers/test_fastapi.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_callout.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_choice.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_contact_person.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_contact_person_list.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_core.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_core_async.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_divider.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_hidden.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_label.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_list_of_one.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_long_text.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_organisation_id.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_timestamp.py +0 -0
- {pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_utils_dict_without_none.py +0 -0
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
strategy:
|
|
17
17
|
matrix:
|
|
18
|
-
python-version: ['3.
|
|
18
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
19
19
|
fail-fast: false
|
|
20
20
|
|
|
21
21
|
steps:
|
|
@@ -29,12 +29,9 @@ jobs:
|
|
|
29
29
|
python -m pip install --upgrade pip
|
|
30
30
|
pip install flit
|
|
31
31
|
flit install --deps develop --extras fastapi
|
|
32
|
-
- name:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- name:
|
|
36
|
-
run: |
|
|
37
|
-
|
|
38
|
-
- name: Check with mypy
|
|
39
|
-
run: |
|
|
40
|
-
mypy pydantic_forms
|
|
32
|
+
- name: Run pre-commit hooks
|
|
33
|
+
uses: pre-commit/action@v3.0.1
|
|
34
|
+
# Use pre-commit mypy for now
|
|
35
|
+
# - name: Check with mypy
|
|
36
|
+
# run: |
|
|
37
|
+
# mypy pydantic_forms
|
|
@@ -9,35 +9,33 @@ jobs:
|
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
strategy:
|
|
11
11
|
matrix:
|
|
12
|
-
python-version: ['3.
|
|
12
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
13
13
|
pydantic-version: ['lockfile']
|
|
14
14
|
fastapi-version: ['lockfile']
|
|
15
15
|
# Test specific older releases to avoid an extremely large test matrix
|
|
16
16
|
include:
|
|
17
|
-
# Older pydantic releases with the oldest + latest supported python version
|
|
17
|
+
# Older pydantic releases with the oldest + second-latest supported python version.
|
|
18
|
+
# (using python 3.14 requires pydantic 2.12 which is currently the latest)
|
|
19
|
+
- python-version: '3.13'
|
|
20
|
+
pydantic-version: '2.11.10'
|
|
21
|
+
fastapi-version: 'lockfile'
|
|
18
22
|
- python-version: '3.13'
|
|
19
23
|
pydantic-version: '2.10.6'
|
|
20
24
|
fastapi-version: 'lockfile'
|
|
21
|
-
- python-version: '3.
|
|
25
|
+
- python-version: '3.10'
|
|
22
26
|
pydantic-version: '2.10.6'
|
|
23
27
|
fastapi-version: 'lockfile'
|
|
24
28
|
- python-version: '3.13'
|
|
25
29
|
pydantic-version: '2.9.2'
|
|
26
30
|
fastapi-version: 'lockfile'
|
|
27
|
-
- python-version: '3.
|
|
31
|
+
- python-version: '3.10'
|
|
28
32
|
pydantic-version: '2.9.2'
|
|
29
33
|
fastapi-version: 'lockfile'
|
|
30
|
-
- python-version: '3.13'
|
|
31
|
-
pydantic-version: '2.8.2'
|
|
32
|
-
fastapi-version: 'lockfile'
|
|
33
|
-
- python-version: '3.9'
|
|
34
|
-
pydantic-version: '2.8.2'
|
|
35
|
-
fastapi-version: 'lockfile'
|
|
36
34
|
# Older fastapi releases with the oldest + latest supported python version
|
|
37
|
-
- python-version: '3.
|
|
35
|
+
- python-version: '3.14'
|
|
38
36
|
pydantic-version: 'lockfile'
|
|
39
37
|
fastapi-version: '0.103.2'
|
|
40
|
-
- python-version: '3.
|
|
38
|
+
- python-version: '3.10'
|
|
41
39
|
pydantic-version: 'lockfile'
|
|
42
40
|
fastapi-version: '0.103.2'
|
|
43
41
|
fail-fast: false
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/psf/black
|
|
3
|
-
rev: 25.
|
|
3
|
+
rev: 25.11.0
|
|
4
4
|
hooks:
|
|
5
5
|
- id: black
|
|
6
|
-
language_version: python3.9
|
|
7
6
|
- repo: https://github.com/asottile/blacken-docs
|
|
8
|
-
rev: 1.
|
|
7
|
+
rev: 1.20.0
|
|
9
8
|
hooks:
|
|
10
9
|
- id: blacken-docs
|
|
11
10
|
additional_dependencies: [black==24.2.0]
|
|
12
11
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
13
12
|
# Ruff version.
|
|
14
|
-
rev: v0.
|
|
13
|
+
rev: v0.14.5
|
|
15
14
|
hooks:
|
|
16
15
|
- id: ruff
|
|
17
16
|
args: [--fix, --exit-non-zero-on-fix, --show-fixes]
|
|
18
17
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
19
|
-
rev:
|
|
18
|
+
rev: v6.0.0
|
|
20
19
|
hooks:
|
|
21
20
|
- id: trailing-whitespace
|
|
22
21
|
- id: end-of-file-fixer
|
|
@@ -28,10 +27,9 @@ repos:
|
|
|
28
27
|
- id: requirements-txt-fixer
|
|
29
28
|
- id: detect-private-key
|
|
30
29
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
31
|
-
rev: v1.
|
|
30
|
+
rev: v1.18.2
|
|
32
31
|
hooks:
|
|
33
32
|
- id: mypy
|
|
34
|
-
language_version: python3.9
|
|
35
33
|
additional_dependencies:
|
|
36
34
|
- pydantic
|
|
37
35
|
- types-toml
|
|
@@ -50,6 +48,6 @@ repos:
|
|
|
50
48
|
- id: python-check-mock-methods
|
|
51
49
|
- id: rst-backticks
|
|
52
50
|
- repo: https://github.com/shellcheck-py/shellcheck-py
|
|
53
|
-
rev: v0.
|
|
51
|
+
rev: v0.11.0.1
|
|
54
52
|
hooks:
|
|
55
53
|
- id: shellcheck
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-forms
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Pydantic-forms engine.
|
|
5
5
|
Home-page: https://github.com/workfloworchestrator/pydantic-forms
|
|
6
6
|
Author: SURF
|
|
7
7
|
Author-email: automation-beheer@surf.nl
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.10,<3.15
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
Classifier: Intended Audience :: Information Technology
|
|
11
11
|
Classifier: Intended Audience :: System Administrators
|
|
@@ -28,16 +28,16 @@ Classifier: Intended Audience :: Developers
|
|
|
28
28
|
Classifier: Intended Audience :: Telecommunications Industry
|
|
29
29
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
30
30
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
31
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
32
31
|
Classifier: Programming Language :: Python :: 3.10
|
|
33
32
|
Classifier: Programming Language :: Python :: 3.11
|
|
34
33
|
Classifier: Programming Language :: Python :: 3.12
|
|
35
34
|
Classifier: Programming Language :: Python :: 3.13
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
36
36
|
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
37
37
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
38
38
|
License-File: LICENSE
|
|
39
39
|
Requires-Dist: more-itertools
|
|
40
|
-
Requires-Dist: pydantic[email]>=2.
|
|
40
|
+
Requires-Dist: pydantic[email]>=2.9.0
|
|
41
41
|
Requires-Dist: pydantic-i18n==0.4.5
|
|
42
42
|
Requires-Dist: toml ; extra == "dev"
|
|
43
43
|
Requires-Dist: bumpversion ; extra == "dev"
|
|
@@ -56,7 +56,7 @@ Requires-Dist: apache-license-check ; extra == "test"
|
|
|
56
56
|
Requires-Dist: black ; extra == "test"
|
|
57
57
|
Requires-Dist: structlog ; extra == "test"
|
|
58
58
|
Requires-Dist: jsonref ; extra == "test"
|
|
59
|
-
Requires-Dist: mypy==1.
|
|
59
|
+
Requires-Dist: mypy==1.18.2 ; extra == "test"
|
|
60
60
|
Requires-Dist: pytest ; extra == "test"
|
|
61
61
|
Requires-Dist: pytest-cov ; extra == "test"
|
|
62
62
|
Requires-Dist: pytest-asyncio ; extra == "test"
|
|
@@ -84,7 +84,7 @@ async def post_form(
|
|
|
84
84
|
except ValidationError as e:
|
|
85
85
|
# Todo: add extra_translation to tr
|
|
86
86
|
tr = PydanticI18n(translations)
|
|
87
|
-
raise FormValidationError(generated_form.__name__, e, tr, locale) from e
|
|
87
|
+
raise FormValidationError(generated_form.__name__, e, tr, locale) from e
|
|
88
88
|
|
|
89
89
|
# Update state with validated_data
|
|
90
90
|
current_state.update(form_validated_data.model_dump())
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Copyright 2019-2023 SURF.
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
# See the License for the specific language governing permissions and
|
|
12
|
+
# limitations under the License.
|
|
13
|
+
from inspect import isasyncgenfunction, isgeneratorfunction
|
|
14
|
+
from typing import Any, Callable
|
|
15
|
+
|
|
16
|
+
import structlog
|
|
17
|
+
from pydantic import BaseModel, ConfigDict, PydanticUndefinedAnnotation, version
|
|
18
|
+
|
|
19
|
+
logger = structlog.get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
PYDANTIC_VERSION = version.version_short()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DisplayOnlyFieldType:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class FormPage(BaseModel):
|
|
30
|
+
model_config = ConfigDict(
|
|
31
|
+
arbitrary_types_allowed=True,
|
|
32
|
+
title="unknown",
|
|
33
|
+
extra="forbid",
|
|
34
|
+
validate_default=True,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def __init__(self, **data: Any):
|
|
38
|
+
frozen_fields = {k: v for k, v in self.__class__.model_fields.items() if v.frozen}
|
|
39
|
+
|
|
40
|
+
def get_value(k: str, v: Any) -> Any:
|
|
41
|
+
if k in frozen_fields:
|
|
42
|
+
return frozen_fields[k].default
|
|
43
|
+
return v
|
|
44
|
+
|
|
45
|
+
mutable_data = {k: get_value(k, v) for k, v in data.items()}
|
|
46
|
+
super().__init__(**mutable_data)
|
|
47
|
+
|
|
48
|
+
if PYDANTIC_VERSION in ("2.9", "2.10", "2.11"):
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def __pydantic_init_subclass__(cls, /, **kwargs: Any) -> None:
|
|
52
|
+
# The default and requiredness of a field is not a property of a field
|
|
53
|
+
# In the case of DisplayOnlyFieldTypes, we do kind of want that.
|
|
54
|
+
# Using this method we set the right properties after the form is created
|
|
55
|
+
needs_rebuild = False
|
|
56
|
+
|
|
57
|
+
for field in cls.model_fields.values():
|
|
58
|
+
if field.frozen:
|
|
59
|
+
field.validate_default = False
|
|
60
|
+
needs_rebuild = True
|
|
61
|
+
|
|
62
|
+
if needs_rebuild:
|
|
63
|
+
try:
|
|
64
|
+
# Fix for #39:
|
|
65
|
+
# Core schema used during validation is constructed before __pydantic_init_subclass__ which means
|
|
66
|
+
# that the field.validate_default change above doesn't take effect.
|
|
67
|
+
# As a workaround, we explicitly rebuild the model to reconstruct the core schema.
|
|
68
|
+
#
|
|
69
|
+
# Downside is that unresolved forward-refs trigger an exception; for now we catch/log/ignore it.
|
|
70
|
+
# From pydantic 2.12 a new hook __pydantic_on_complete__ can be used to perform the rebuild instead.
|
|
71
|
+
# https://github.com/pydantic/pydantic/pull/11762
|
|
72
|
+
cls.model_rebuild(force=True)
|
|
73
|
+
except PydanticUndefinedAnnotation as exc:
|
|
74
|
+
logger.warning(
|
|
75
|
+
"Failed to rebuild model due to undefined annotation, frozen fields may not work as expected",
|
|
76
|
+
undefined_annotation=exc.name,
|
|
77
|
+
model=cls.__name__,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
else: # pydantic >= 2.12
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def __pydantic_on_complete__(cls) -> None:
|
|
84
|
+
# The default and requiredness of a field is not a property of a field
|
|
85
|
+
# In the case of DisplayOnlyFieldTypes, we do kind of want that.
|
|
86
|
+
# Using this method we set the right properties after the form is created
|
|
87
|
+
needs_rebuild = False
|
|
88
|
+
|
|
89
|
+
for field in cls.model_fields.values():
|
|
90
|
+
if field.frozen:
|
|
91
|
+
field.validate_default = False
|
|
92
|
+
needs_rebuild = True
|
|
93
|
+
|
|
94
|
+
if needs_rebuild:
|
|
95
|
+
cls.model_rebuild(force=True)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
FORMS: dict[str, Callable] = {}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def register_form(key: str, form: Callable) -> None:
|
|
102
|
+
logger.info("Current Forms", forms=FORMS, new_key=key)
|
|
103
|
+
if key in FORMS and form is not FORMS[key]:
|
|
104
|
+
raise Exception(f"Trying to re-register form {key} with a different function")
|
|
105
|
+
|
|
106
|
+
if not isasyncgenfunction(form) and not isgeneratorfunction(form):
|
|
107
|
+
raise Exception(f"Trying to register form {key} function {form} which is not an (async) generator function")
|
|
108
|
+
|
|
109
|
+
FORMS[key] = form
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def list_forms() -> list[str]:
|
|
113
|
+
return list(FORMS.keys())
|
|
@@ -79,7 +79,7 @@ def post_form(
|
|
|
79
79
|
except ValidationError as e:
|
|
80
80
|
# Todo: add extra_translation to tr
|
|
81
81
|
tr = PydanticI18n(translations)
|
|
82
|
-
raise FormValidationError(generated_form.__name__, e, tr, locale) from e
|
|
82
|
+
raise FormValidationError(generated_form.__name__, e, tr, locale) from e
|
|
83
83
|
|
|
84
84
|
# Update state with validated_data
|
|
85
85
|
current_state.update(form_validated_data.model_dump())
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
+
from types import UnionType
|
|
2
3
|
from typing import Any, AsyncGenerator, Callable, Generator, Type, TypeVar, Union
|
|
3
4
|
|
|
5
|
+
from pydantic.main import BaseModel
|
|
4
6
|
from typing_extensions import TypedDict
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
# python3.10 introduces types.UnionType for the new union and optional type defs.
|
|
8
|
-
from types import UnionType # type: ignore # 3.9 compatibility
|
|
9
|
-
|
|
10
|
-
union_types = [Union, UnionType]
|
|
11
|
-
except ImportError:
|
|
12
|
-
union_types = [Union]
|
|
13
|
-
from pydantic.main import BaseModel
|
|
8
|
+
union_types = [Union, UnionType]
|
|
14
9
|
|
|
15
10
|
UUIDstr = str
|
|
16
11
|
State = dict[str, Any]
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/read_only.py
RENAMED
|
@@ -93,7 +93,7 @@ def read_only_list(default: list[Any] | None = None) -> Any:
|
|
|
93
93
|
|
|
94
94
|
return Annotated[
|
|
95
95
|
list[default_item_type],
|
|
96
|
-
Field(default, json_schema_extra=json_schema),
|
|
96
|
+
Field(default, json_schema_extra=json_schema),
|
|
97
97
|
AfterValidator(validate_list),
|
|
98
98
|
PlainSerializer(serialize_list, when_used="json"),
|
|
99
99
|
]
|
|
@@ -131,7 +131,7 @@ def read_only_field(default: Any, merge_type: Any | None = None) -> Any:
|
|
|
131
131
|
|
|
132
132
|
read_only_type = Annotated[
|
|
133
133
|
Literal[default], # type: ignore[valid-type]
|
|
134
|
-
Field(default, json_schema_extra=json_schema),
|
|
134
|
+
Field(default, json_schema_extra=json_schema),
|
|
135
135
|
BeforeValidator(validate),
|
|
136
136
|
PlainSerializer(serialize_json, when_used="json"),
|
|
137
137
|
]
|
|
@@ -30,21 +30,21 @@ classifiers = [
|
|
|
30
30
|
"Intended Audience :: Telecommunications Industry",
|
|
31
31
|
"License :: OSI Approved :: Apache Software License",
|
|
32
32
|
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
-
"Programming Language :: Python :: 3.9",
|
|
34
33
|
"Programming Language :: Python :: 3.10",
|
|
35
34
|
"Programming Language :: Python :: 3.11",
|
|
36
35
|
"Programming Language :: Python :: 3.12",
|
|
37
36
|
"Programming Language :: Python :: 3.13",
|
|
37
|
+
"Programming Language :: Python :: 3.14",
|
|
38
38
|
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
|
39
39
|
"Topic :: Internet :: WWW/HTTP",
|
|
40
40
|
]
|
|
41
41
|
requires = [
|
|
42
42
|
"more-itertools",
|
|
43
|
-
"pydantic[email]>=2.
|
|
43
|
+
"pydantic[email]>=2.9.0",
|
|
44
44
|
"pydantic-i18n==0.4.5"
|
|
45
45
|
]
|
|
46
46
|
description-file = "README.md"
|
|
47
|
-
requires-python = ">=3.
|
|
47
|
+
requires-python = ">=3.10,<3.15"
|
|
48
48
|
|
|
49
49
|
[tool.flit.metadata.urls]
|
|
50
50
|
Documentation = "https://github.com/workfloworchestrator/pydantic-forms/blob/main/README.md"
|
|
@@ -55,7 +55,7 @@ test = [
|
|
|
55
55
|
"black",
|
|
56
56
|
"structlog",
|
|
57
57
|
"jsonref",
|
|
58
|
-
"mypy==1.
|
|
58
|
+
"mypy==1.18.2",
|
|
59
59
|
"pytest",
|
|
60
60
|
"pytest-cov",
|
|
61
61
|
"pytest-asyncio",
|
|
@@ -96,7 +96,7 @@ fastapi = [
|
|
|
96
96
|
|
|
97
97
|
[tool.black]
|
|
98
98
|
line-length = 120
|
|
99
|
-
target-version = ["
|
|
99
|
+
target-version = ["py310"]
|
|
100
100
|
exclude = '''
|
|
101
101
|
(
|
|
102
102
|
/(
|
|
@@ -126,9 +126,10 @@ exclude = [
|
|
|
126
126
|
"venv",
|
|
127
127
|
".venv",
|
|
128
128
|
"docs",
|
|
129
|
-
"tests"
|
|
130
129
|
]
|
|
131
130
|
lint.ignore = [
|
|
131
|
+
"B904",
|
|
132
|
+
"B905",
|
|
132
133
|
"C417",
|
|
133
134
|
"D100",
|
|
134
135
|
"D101",
|
|
@@ -140,18 +141,22 @@ lint.ignore = [
|
|
|
140
141
|
"D107",
|
|
141
142
|
"D202",
|
|
142
143
|
"E501",
|
|
143
|
-
"N806",
|
|
144
|
-
"B905",
|
|
145
|
-
"N805",
|
|
146
|
-
"B904",
|
|
147
|
-
"N803",
|
|
148
144
|
"N801",
|
|
149
|
-
"N815",
|
|
150
145
|
"N802",
|
|
146
|
+
"N803",
|
|
147
|
+
"N805",
|
|
148
|
+
"N806",
|
|
149
|
+
"N815",
|
|
150
|
+
"S101", # use of assert
|
|
151
151
|
]
|
|
152
152
|
line-length = 120
|
|
153
153
|
lint.select = ["B", "C", "D", "E", "F", "I", "N", "RET", "S", "T", "W"]
|
|
154
|
-
target-version = "
|
|
154
|
+
target-version = "py310"
|
|
155
|
+
|
|
156
|
+
[tool.ruff.lint.per-file-ignores]
|
|
157
|
+
"tests/*" = [
|
|
158
|
+
"D205", # blank line required
|
|
159
|
+
]
|
|
155
160
|
|
|
156
161
|
[tool.lint.flake8-tidy-imports]
|
|
157
162
|
ban-relative-imports = "all"
|
|
@@ -36,8 +36,7 @@ disallow_untyped_decorators = True
|
|
|
36
36
|
no_implicit_optional = True
|
|
37
37
|
strict_optional = True
|
|
38
38
|
namespace_packages = true
|
|
39
|
-
|
|
40
|
-
warn_unused_ignores = False
|
|
39
|
+
warn_unused_ignores = True
|
|
41
40
|
warn_redundant_casts = True
|
|
42
41
|
; Disable due to flaky results in mypy itself
|
|
43
42
|
;warn_return_any = True
|
|
@@ -7,7 +7,7 @@ def assert_equal_ignore_key(expected, actual, ignore_keys):
|
|
|
7
7
|
def deep_remove_keys(d, keys_to_ignore):
|
|
8
8
|
if isinstance(d, dict):
|
|
9
9
|
return {k: deep_remove_keys(v, keys_to_ignore) for k, v in d.items() if k not in keys_to_ignore}
|
|
10
|
-
|
|
10
|
+
if isinstance(d, list):
|
|
11
11
|
return [deep_remove_keys(i, keys_to_ignore) for i in d]
|
|
12
12
|
return d
|
|
13
13
|
|
|
@@ -4,8 +4,6 @@ from pydantic_core import ValidationError
|
|
|
4
4
|
from pydantic_forms.core import FormPage
|
|
5
5
|
from pydantic_forms.validators import Choice, choice_list
|
|
6
6
|
|
|
7
|
-
from tests.unit_tests.helpers import PYDANTIC_VERSION
|
|
8
|
-
|
|
9
7
|
|
|
10
8
|
def test_choice_list():
|
|
11
9
|
class LegChoice(Choice):
|
|
@@ -152,15 +150,11 @@ def test_choice_list_constraint_at_least_one_item(Form):
|
|
|
152
150
|
|
|
153
151
|
errors = exc_info.value.errors(include_url=False, include_context=False)
|
|
154
152
|
|
|
155
|
-
if PYDANTIC_VERSION == "2.8":
|
|
156
|
-
message = "List should have at least 1 item after validation, not 0"
|
|
157
|
-
else:
|
|
158
|
-
message = "Value should have at least 1 item after validation, not 0"
|
|
159
153
|
expected = [
|
|
160
154
|
{
|
|
161
155
|
"input": [],
|
|
162
156
|
"loc": ("choice",),
|
|
163
|
-
"msg":
|
|
157
|
+
"msg": "Value should have at least 1 item after validation, not 0",
|
|
164
158
|
"type": "too_short",
|
|
165
159
|
}
|
|
166
160
|
]
|
|
@@ -3,9 +3,6 @@ from pytest import raises
|
|
|
3
3
|
|
|
4
4
|
from pydantic_forms.core import FormPage
|
|
5
5
|
from pydantic_forms.validators import unique_conlist
|
|
6
|
-
from pydantic.version import version_short as pydantic_version_short
|
|
7
|
-
|
|
8
|
-
from tests.unit_tests.helpers import PYDANTIC_VERSION
|
|
9
6
|
|
|
10
7
|
|
|
11
8
|
def test_constrained_list_good():
|
|
@@ -77,15 +74,11 @@ def test_constrained_list_too_short():
|
|
|
77
74
|
|
|
78
75
|
errors = exc_info.value.errors(include_url=False, include_context=False)
|
|
79
76
|
|
|
80
|
-
if PYDANTIC_VERSION == "2.8":
|
|
81
|
-
message = "List should have at least 1 item after validation, not 0"
|
|
82
|
-
else:
|
|
83
|
-
message = "Value should have at least 1 item after validation, not 0"
|
|
84
77
|
expected = [
|
|
85
78
|
{
|
|
86
79
|
"input": [],
|
|
87
80
|
"loc": ("v",),
|
|
88
|
-
"msg":
|
|
81
|
+
"msg": "Value should have at least 1 item after validation, not 0",
|
|
89
82
|
"type": "too_short",
|
|
90
83
|
}
|
|
91
84
|
]
|
|
@@ -117,15 +110,12 @@ def test_constrained_list_inherit_constraints():
|
|
|
117
110
|
UniqueConListModel(v=[])
|
|
118
111
|
|
|
119
112
|
errors = exc_info.value.errors(include_url=False, include_context=False)
|
|
120
|
-
|
|
121
|
-
message = "List should have at least 1 item after validation, not 0"
|
|
122
|
-
else:
|
|
123
|
-
message = "Value should have at least 1 item after validation, not 0"
|
|
113
|
+
|
|
124
114
|
assert errors == [
|
|
125
115
|
{
|
|
126
116
|
"input": [],
|
|
127
117
|
"loc": ("v",),
|
|
128
|
-
"msg":
|
|
118
|
+
"msg": "Value should have at least 1 item after validation, not 0",
|
|
129
119
|
"type": "too_short",
|
|
130
120
|
# "ctx": {"limit_value": 1},
|
|
131
121
|
}
|
|
@@ -2,7 +2,6 @@ from uuid import uuid4
|
|
|
2
2
|
|
|
3
3
|
from pydantic_forms.core import FormPage
|
|
4
4
|
from pydantic_forms.validators import DisplaySubscription, Label, migration_summary
|
|
5
|
-
from tests.unit_tests.helpers import PYDANTIC_VERSION
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def test_display_subscription():
|
|
@@ -36,11 +35,6 @@ def test_display_only_schema():
|
|
|
36
35
|
label: Label
|
|
37
36
|
summary: Summary
|
|
38
37
|
|
|
39
|
-
if PYDANTIC_VERSION == "2.8":
|
|
40
|
-
summary_ref = {"allOf": [{"$ref": "#/$defs/MigrationSummaryValue"}]}
|
|
41
|
-
else:
|
|
42
|
-
summary_ref = {"$ref": "#/$defs/MigrationSummaryValue"}
|
|
43
|
-
|
|
44
38
|
expected = {
|
|
45
39
|
"$defs": {"MigrationSummaryValue": {"properties": {}, "title": "MigrationSummaryValue", "type": "object"}},
|
|
46
40
|
"additionalProperties": False,
|
|
@@ -59,7 +53,7 @@ def test_display_only_schema():
|
|
|
59
53
|
"type": "string",
|
|
60
54
|
},
|
|
61
55
|
"summary": {
|
|
62
|
-
|
|
56
|
+
"$ref": "#/$defs/MigrationSummaryValue",
|
|
63
57
|
"default": None,
|
|
64
58
|
"format": "summary",
|
|
65
59
|
"type": "string",
|
|
@@ -3,7 +3,6 @@ from pydantic import ValidationError
|
|
|
3
3
|
|
|
4
4
|
from pydantic_forms.core import FormPage
|
|
5
5
|
from pydantic_forms.validators import ListOfTwo
|
|
6
|
-
from tests.unit_tests.helpers import PYDANTIC_VERSION
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
@pytest.fixture(name="Form")
|
|
@@ -23,15 +22,12 @@ def test_list_of_two_min_items(Form):
|
|
|
23
22
|
assert Form(two=[1])
|
|
24
23
|
|
|
25
24
|
errors = error_info.value.errors(include_url=False, include_context=False)
|
|
26
|
-
|
|
27
|
-
message = "List should have at least 2 items after validation, not 1"
|
|
28
|
-
else:
|
|
29
|
-
message = "Value should have at least 2 items after validation, not 1"
|
|
25
|
+
|
|
30
26
|
expected = [
|
|
31
27
|
{
|
|
32
28
|
"input": [1],
|
|
33
29
|
"loc": ("two",),
|
|
34
|
-
"msg":
|
|
30
|
+
"msg": "Value should have at least 2 items after validation, not 1",
|
|
35
31
|
"type": "too_short",
|
|
36
32
|
}
|
|
37
33
|
]
|
|
@@ -43,15 +39,12 @@ def test_list_of_two_max_items(Form):
|
|
|
43
39
|
assert Form(two=[1, 2, 3])
|
|
44
40
|
|
|
45
41
|
errors = error_info.value.errors(include_url=False, include_context=False)
|
|
46
|
-
|
|
47
|
-
message = "List should have at most 2 items after validation, not 3"
|
|
48
|
-
else:
|
|
49
|
-
message = "Value should have at most 2 items after validation, not 3"
|
|
42
|
+
|
|
50
43
|
expected = [
|
|
51
44
|
{
|
|
52
45
|
"input": [1, 2, 3],
|
|
53
46
|
"loc": ("two",),
|
|
54
|
-
"msg":
|
|
47
|
+
"msg": "Value should have at most 2 items after validation, not 3",
|
|
55
48
|
"type": "too_long",
|
|
56
49
|
},
|
|
57
50
|
]
|
|
@@ -2,7 +2,6 @@ from uuid import uuid4
|
|
|
2
2
|
|
|
3
3
|
from pydantic_forms.core import FormPage
|
|
4
4
|
from pydantic_forms.validators import DisplaySubscription, Label, migration_summary
|
|
5
|
-
from tests.unit_tests.helpers import PYDANTIC_VERSION
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def test_display_default():
|
|
@@ -34,17 +33,12 @@ def test_migration_summary_schema():
|
|
|
34
33
|
class Form(FormPage):
|
|
35
34
|
ms: Summary
|
|
36
35
|
|
|
37
|
-
if PYDANTIC_VERSION == "2.8":
|
|
38
|
-
ms_ref = {"allOf": [{"$ref": "#/$defs/MigrationSummaryValue"}]}
|
|
39
|
-
else:
|
|
40
|
-
ms_ref = {"$ref": "#/$defs/MigrationSummaryValue"}
|
|
41
|
-
|
|
42
36
|
expected = {
|
|
43
37
|
"$defs": {"MigrationSummaryValue": {"properties": {}, "title": "MigrationSummaryValue", "type": "object"}},
|
|
44
38
|
"additionalProperties": False,
|
|
45
39
|
"properties": {
|
|
46
40
|
"ms": {
|
|
47
|
-
|
|
41
|
+
"$ref": "#/$defs/MigrationSummaryValue",
|
|
48
42
|
"default": None,
|
|
49
43
|
"format": "summary",
|
|
50
44
|
"type": "string",
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from uuid import UUID
|
|
3
3
|
|
|
4
|
-
from pydantic.config import JsonDict
|
|
5
4
|
import pytest
|
|
6
5
|
from pydantic import BaseModel, ValidationError
|
|
7
|
-
|
|
8
|
-
from pydantic.version import version_short as pydantic_version_short
|
|
6
|
+
from pydantic.config import JsonDict
|
|
9
7
|
|
|
10
8
|
from pydantic_forms.core import FormPage
|
|
11
9
|
from pydantic_forms.types import strEnum
|
|
12
|
-
from pydantic_forms.validators import read_only_field, read_only_list, LongText, OrganisationId
|
|
13
10
|
from pydantic_forms.utils.schema import merge_json_schema
|
|
11
|
+
from pydantic_forms.validators import LongText, OrganisationId, read_only_field, read_only_list
|
|
14
12
|
from tests.unit_tests.helpers import PYDANTIC_VERSION
|
|
15
13
|
|
|
16
14
|
|
|
@@ -36,7 +34,7 @@ def test_read_only_field_schema(read_only_value, schema_value, schema_type, othe
|
|
|
36
34
|
class Form(FormPage):
|
|
37
35
|
read_only: read_only_field(read_only_value)
|
|
38
36
|
|
|
39
|
-
if PYDANTIC_VERSION in ("2.
|
|
37
|
+
if PYDANTIC_VERSION in ("2.9",):
|
|
40
38
|
# Field that was removed in 2.10 https://github.com/pydantic/pydantic/pull/10692
|
|
41
39
|
enum_value = str(read_only_value) if isinstance(read_only_value, UUID) else read_only_value
|
|
42
40
|
enum = {"enum": [enum_value]}
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_utils_to_serializable.py
RENAMED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Test UUID serialization
|
|
2
|
-
from dataclasses import
|
|
2
|
+
from dataclasses import asdict, dataclass
|
|
3
3
|
from datetime import datetime
|
|
4
|
-
from ipaddress import
|
|
4
|
+
from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network
|
|
5
5
|
from uuid import UUID
|
|
6
6
|
|
|
7
|
-
from pydantic_forms.utils.json import to_serializable
|
|
8
7
|
import pytest
|
|
9
8
|
|
|
9
|
+
from pydantic_forms.utils.json import to_serializable
|
|
10
|
+
|
|
10
11
|
|
|
11
12
|
def test_to_serializable_uuid():
|
|
12
13
|
test_uuid = UUID("12345678123456781234567812345678")
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Copyright 2019-2023 SURF.
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
-
# you may not use this file except in compliance with the License.
|
|
4
|
-
# You may obtain a copy of the License at
|
|
5
|
-
#
|
|
6
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
#
|
|
8
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
# See the License for the specific language governing permissions and
|
|
12
|
-
# limitations under the License.
|
|
13
|
-
from inspect import isasyncgenfunction, isgeneratorfunction
|
|
14
|
-
from typing import Any, Callable
|
|
15
|
-
|
|
16
|
-
import structlog
|
|
17
|
-
from pydantic import BaseModel, ConfigDict, PydanticUndefinedAnnotation
|
|
18
|
-
|
|
19
|
-
logger = structlog.get_logger(__name__)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class DisplayOnlyFieldType:
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class FormPage(BaseModel):
|
|
27
|
-
model_config = ConfigDict(
|
|
28
|
-
arbitrary_types_allowed=True,
|
|
29
|
-
title="unknown",
|
|
30
|
-
extra="forbid",
|
|
31
|
-
validate_default=True,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
def __init__(self, **data: Any):
|
|
35
|
-
frozen_fields = {k: v for k, v in self.__class__.model_fields.items() if v.frozen}
|
|
36
|
-
|
|
37
|
-
def get_value(k: str, v: Any) -> Any:
|
|
38
|
-
if k in frozen_fields:
|
|
39
|
-
return frozen_fields[k].default
|
|
40
|
-
return v
|
|
41
|
-
|
|
42
|
-
mutable_data = {k: get_value(k, v) for k, v in data.items()}
|
|
43
|
-
super().__init__(**mutable_data)
|
|
44
|
-
|
|
45
|
-
@classmethod
|
|
46
|
-
def __pydantic_init_subclass__(cls, /, **kwargs: Any) -> None:
|
|
47
|
-
# The default and requiredness of a field is not a property of a field
|
|
48
|
-
# In the case of DisplayOnlyFieldTypes, we do kind of want that.
|
|
49
|
-
# Using this method we set the right properties after the form is created
|
|
50
|
-
needs_rebuild = False
|
|
51
|
-
|
|
52
|
-
for field in cls.model_fields.values():
|
|
53
|
-
if field.frozen:
|
|
54
|
-
field.validate_default = False
|
|
55
|
-
needs_rebuild = True
|
|
56
|
-
|
|
57
|
-
if needs_rebuild:
|
|
58
|
-
try:
|
|
59
|
-
# Fix for #39:
|
|
60
|
-
# Core schema used during validation is constructed before __pydantic_init_subclass__ which means
|
|
61
|
-
# that the field.validate_default change above doesn't take effect.
|
|
62
|
-
# As a workaround, we explicitly rebuild the model to reconstruct the core schema.
|
|
63
|
-
#
|
|
64
|
-
# Downside is that unresolved forward-refs trigger an exception; for now we catch/log/ignore it.
|
|
65
|
-
# From pydantic 2.12 a new hook __pydantic_on_complete__ can be used to perform the rebuild instead.
|
|
66
|
-
# https://github.com/pydantic/pydantic/pull/11762
|
|
67
|
-
cls.model_rebuild(force=True)
|
|
68
|
-
except PydanticUndefinedAnnotation as exc:
|
|
69
|
-
logger.warning(
|
|
70
|
-
"Failed to rebuild model due to undefined annotation, frozen fields may not work as expected",
|
|
71
|
-
undefined_annotation=exc.name,
|
|
72
|
-
model=cls.__name__,
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
FORMS: dict[str, Callable] = {}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def register_form(key: str, form: Callable) -> None:
|
|
80
|
-
logger.info("Current Forms", forms=FORMS, new_key=key)
|
|
81
|
-
if key in FORMS and form is not FORMS[key]:
|
|
82
|
-
raise Exception(f"Trying to re-register form {key} with a different function")
|
|
83
|
-
|
|
84
|
-
if not isasyncgenfunction(form) and not isgeneratorfunction(form):
|
|
85
|
-
raise Exception(f"Trying to register form {key} function {form} which is not an (async) generator function")
|
|
86
|
-
|
|
87
|
-
FORMS[key] = form
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def list_forms() -> list[str]:
|
|
91
|
-
return list(FORMS.keys())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/__init__.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/accept.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/callout.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/choice.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/choice_list.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/contact_person.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/divider.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/hidden.py
RENAMED
|
File without changes
|
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/list_of_one.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/list_of_two.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/long_text.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/pydantic_forms/validators/components/timestamp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/exception_handlers/__init__.py
RENAMED
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/exception_handlers/test_fastapi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_forms-2.2.0 → pydantic_forms-2.3.0}/tests/unit_tests/test_utils_dict_without_none.py
RENAMED
|
File without changes
|