Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pydantic for openSUSE:Factory
checked in at 2023-01-04 17:53:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pydantic (Old)
and /work/SRC/openSUSE:Factory/.python-pydantic.new.1563 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pydantic"
Wed Jan 4 17:53:14 2023 rev:15 rq:1055778 version:1.10.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pydantic/python-pydantic.changes
2022-09-09 18:29:34.269274775 +0200
+++
/work/SRC/openSUSE:Factory/.python-pydantic.new.1563/python-pydantic.changes
2023-01-04 17:53:24.926469023 +0100
@@ -1,0 +2,27 @@
+Mon Jan 2 20:22:05 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to v1.10.4:
+ * Change dependency to typing-extensions>=4.2.0, #4885 by @samuelcolvin
+ * fix parsing of custom root models, #4883 by @gou177
+ * fix: use dataclass proxy for frozen or empty dataclasses, #4878 by
+ @PrettyWood
+ * Fix schema and schema_json on models where a model instance is a one of
+ default values, #4781 by @Bobronium
+ * Add Jina AI to sponsors on docs index page, #4767 by @samuelcolvin
+ * fix: support assignment on DataclassProxy, #4695 by @PrettyWood
+ * Add postgresql+psycopg as allowed scheme for PostgreDsn to make it
+ usable with SQLAlchemy 2, #4689 by @morian
+ * Allow dict schemas to have both patternProperties and
+ additionalProperties, #4641 by @jparise
+ * Fixes error passing None for optional lists with unique_items, #4568 by
+ @mfulgo
+ * Fix GenericModel with Callable param raising a TypeError, #4551 by
+ @mfulgo
+ * Fix field regex with StrictStr type annotation, #4538 by @sisp
+ * Correct dataclass_transform keyword argument name from field_descriptors
+ to field_specifiers, #4500 by @samuelcolvin
+ * fix: avoid multiple calls of __post_init__ when dataclasses are
+ inherited, #4487 by @PrettyWood
+ * Reduce the size of binary wheels, #2276 by @samuelcolvin
+
+-------------------------------------------------------------------
Old:
----
pydantic-1.10.2.tar.gz
New:
----
pydantic-1.10.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pydantic.spec ++++++
--- /var/tmp/diff_new_pack.SKSQ1i/_old 2023-01-04 17:53:25.398471806 +0100
+++ /var/tmp/diff_new_pack.SKSQ1i/_new 2023-01-04 17:53:25.402471829 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-pydantic
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
# Copyright (c) 2019, Martin Hauke <[email protected]>
#
# All modifications and additions to the file contributed by third parties
@@ -20,12 +20,12 @@
%{?!python_module:%define python_module() python3-%{**}}
%define skip_python2 1
Name: python-pydantic
-Version: 1.10.2
+Version: 1.10.4
Release: 0
Summary: Data validation and settings management using python type
hinting
License: MIT
-URL: https://github.com/samuelcolvin/pydantic
-Source:
https://github.com/samuelcolvin/pydantic/archive/v%{version}.tar.gz#/pydantic-%{version}.tar.gz
+URL: https://github.com/pydantic/pydantic
+Source:
https://github.com/pydantic/pydantic/archive/v%{version}.tar.gz#/pydantic-%{version}.tar.gz
# PATCH-FIX-OPENSUSE Ignore DeprecationWarning until requests-toolbelt is fixed
# (Pulled in by email-validator)
Patch0: ignore-urllib3-pyopenssl-warning.patch
@@ -35,10 +35,10 @@
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module python-dotenv >= 0.10.4}
BuildRequires: %{python_module setuptools}
-BuildRequires: %{python_module typing_extensions >= 4.1.0}
+BuildRequires: %{python_module typing_extensions >= 4.2.0}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-typing_extensions >= 4.1.0
+Requires: python-typing_extensions >= 4.2.0
Suggests: python-email-validator >= 1.0.3
Suggests: python-python-dotenv >= 0.10.4
BuildArch: noarch
++++++ pydantic-1.10.2.tar.gz -> pydantic-1.10.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/.github/workflows/ci.yml
new/pydantic-1.10.4/.github/workflows/ci.yml
--- old/pydantic-1.10.2/.github/workflows/ci.yml 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/.github/workflows/ci.yml 2022-12-30
10:53:51.000000000 +0100
@@ -4,6 +4,7 @@
push:
branches:
- main
+ - 1.10.X-fixes
tags:
- '**'
pull_request: {}
@@ -27,7 +28,7 @@
${{ env.pythonLocation }}
.mypy_cache
key: >
- lint
+ lint-v2
${{ runner.os }}
${{ env.pythonLocation }}
${{ hashFiles('tests/requirements-linting.txt') }}
@@ -77,7 +78,7 @@
with:
path: ${{ env.pythonLocation }}
key: >
- docs-build
+ docs-build-v2
${{ runner.os }}
${{ env.pythonLocation }}
${{ hashFiles('setup.py') }}
@@ -103,7 +104,7 @@
strategy:
fail-fast: false
matrix:
- python-version: ['3.7', '3.8', '3.9', '3.10', '3.11.0-rc.1']
+ python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
env:
PYTHON: ${{ matrix.python-version }}
OS: ubuntu
@@ -121,7 +122,7 @@
with:
path: ${{ env.pythonLocation }}
key: >
- test-linux-compiled
+ test-linux-compiled-v2
${{ runner.os }}
${{ env.pythonLocation }}
${{ hashFiles('setup.py') }}
@@ -182,7 +183,7 @@
with:
path: ${{ env.pythonLocation }}
key: >
- test-not-compiled
+ test-not-compiled-v2
${{ runner.os }}
${{ env.pythonLocation }}
${{ hashFiles('setup.py') }}
@@ -307,8 +308,6 @@
build:
name: build py3.${{ matrix.python-version }} on ${{ matrix.platform ||
matrix.os }}
- needs: [lint, test-linux-compiled, test-not-compiled, test-old-mypy,
test-fastapi]
- if: "success() && (startsWith(github.ref, 'refs/tags/') || github.ref ==
'refs/heads/main')"
strategy:
fail-fast: false
matrix:
@@ -366,9 +365,62 @@
name: pypi_files
path: dist
+ # https://github.com/marketplace/actions/alls-green#why
+ check: # This job does nothing and is only used for the branch protection
+
+ if: always()
+
+ needs:
+ - lint
+ - docs-build
+ - test-linux-compiled
+ - test-not-compiled
+ - test-old-mypy
+ - test-fastapi
+ - build
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Decide whether the needed jobs succeeded or failed
+ uses: re-actors/alls-green@release/v1
+ with:
+ jobs: ${{ toJSON(needs) }}
+
+ inspect-pypi-assets:
+ needs: [build]
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: get dist artifacts
+ uses: actions/download-artifact@v3
+ with:
+ name: pypi_files
+ path: dist
+
+ - name: list dist files
+ run: |
+ ls -lh dist/
+ echo "`ls dist | wc -l` files"
+
+ - name: extract and list sdist file
+ run: |
+ mkdir sdist-files
+ tar -xvf dist/*.tar.gz -C sdist-files
+ tree -a sdist-files
+
+ - name: extract and list wheel file
+ run: |
+ ls dist/*cp310-manylinux*x86_64.whl | head -n 1
+ python -m zipfile --list `ls dist/*cp310-manylinux*x86_64.whl | head
-n 1`
+
deploy:
name: Deploy
- needs: build
+ needs:
+ - check
+ - build
if: "success() && startsWith(github.ref, 'refs/tags/')"
runs-on: ubuntu-latest
@@ -412,6 +464,9 @@
- name: publish docs
if: '!fromJSON(steps.check-tag.outputs.IS_PRERELEASE)'
- run: make publish-docs
+ uses: cloudflare/[email protected]
+ with:
+ apiToken: ${{ secrets.cloudflare_api_token }}
+ command: pages publish --project-name=pydantic-docs --branch=main
site
env:
- NETLIFY: ${{ secrets.netlify_token }}
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.cloudflare_account_id }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/.hooky.toml
new/pydantic-1.10.4/.hooky.toml
--- old/pydantic-1.10.2/.hooky.toml 1970-01-01 01:00:00.000000000 +0100
+++ new/pydantic-1.10.4/.hooky.toml 2022-12-30 10:53:51.000000000 +0100
@@ -0,0 +1,4 @@
+# configuring https://github.com/pydantic/hooky
+[tool.hooky]
+reviewers = ['samuelcolvin', 'PrettyWood', 'hramezani']
+require_change_file = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/HISTORY.md
new/pydantic-1.10.4/HISTORY.md
--- old/pydantic-1.10.2/HISTORY.md 2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/HISTORY.md 2022-12-30 10:53:51.000000000 +0100
@@ -1,3 +1,25 @@
+## v1.10.4 (2022-12-30)
+
+* Change dependency to `typing-extensions>=4.2.0`, #4885 by @samuelcolvin
+
+## v1.10.3 (2022-12-29)
+
+**NOTE: v1.10.3 was ["yanked"](https://pypi.org/help/#yanked) from PyPI due to
#4885 which is fixed in v1.10.4**
+
+* fix parsing of custom root models, #4883 by @gou177
+* fix: use dataclass proxy for frozen or empty dataclasses, #4878 by
@PrettyWood
+* Fix `schema` and `schema_json` on models where a model instance is a one of
default values, #4781 by @Bobronium
+* Add Jina AI to sponsors on docs index page, #4767 by @samuelcolvin
+* fix: support assignment on `DataclassProxy`, #4695 by @PrettyWood
+* Add `postgresql+psycopg` as allowed scheme for `PostgreDsn` to make it
usable with SQLAlchemy 2, #4689 by @morian
+* Allow dict schemas to have both `patternProperties` and
`additionalProperties`, #4641 by @jparise
+* Fixes error passing None for optional lists with `unique_items`, #4568 by
@mfulgo
+* Fix `GenericModel` with `Callable` param raising a `TypeError`, #4551 by
@mfulgo
+* Fix field regex with `StrictStr` type annotation, #4538 by @sisp
+* Correct `dataclass_transform` keyword argument name from `field_descriptors`
to `field_specifiers`, #4500 by @samuelcolvin
+* fix: avoid multiple calls of `__post_init__` when dataclasses are inherited,
#4487 by @PrettyWood
+* Reduce the size of binary wheels, #2276 by @samuelcolvin
+
## v1.10.2 (2022-09-05)
* **Revert Change:** Revert percent encoding of URL parts which was originally
added in #4224, #4470 by @samuelcolvin
@@ -159,10 +181,10 @@
### Highlights
* add Python 3.10 support, #2885 by @PrettyWood
-* [Discriminated
unions](https://pydantic-docs.helpmanual.io/usage/types/#discriminated-unions-aka-tagged-unions),
#619 by @PrettyWood
-* [`Config.smart_union` for better union
logic](https://pydantic-docs.helpmanual.io/usage/model_config/#smart-union),
#2092 by @PrettyWood
+* [Discriminated
unions](https://docs.pydantic.dev/usage/types/#discriminated-unions-aka-tagged-unions),
#619 by @PrettyWood
+* [`Config.smart_union` for better union
logic](https://docs.pydantic.dev/usage/model_config/#smart-union), #2092 by
@PrettyWood
* Binaries for Macos M1 CPUs, #3498 by @samuelcolvin
-* Complex types can be set via [nested environment
variables](https://pydantic-docs.helpmanual.io/usage/settings/#parsing-environment-variable-values),
e.g. `foo___bar`, #3159 by @Air-Mark
+* Complex types can be set via [nested environment
variables](https://docs.pydantic.dev/usage/settings/#parsing-environment-variable-values),
e.g. `foo___bar`, #3159 by @Air-Mark
* add a dark mode to _pydantic_ documentation, #2913 by @gbdlin
* Add support for autocomplete in VS Code via `__dataclass_transform__`, #2721
by @tiangolo
* Add "exclude" as a field parameter so that it can be configured using model
config, #660 by @daviskirk
@@ -193,7 +215,7 @@
`pydantic.fields.ModelField`) to `__modify_schema__()` if present, #3434 by
@jasujm
* Fix issue when pydantic fail to parse `typing.ClassVar` string type
annotation, #3401 by @uriyyo
* Mention Python >= 3.9.2 as an alternative to `typing_extensions.TypedDict`,
#3374 by @BvB93
-* Changed the validator method name in the [Custom Errors
example](https://pydantic-docs.helpmanual.io/usage/models/#custom-errors)
+* Changed the validator method name in the [Custom Errors
example](https://docs.pydantic.dev/usage/models/#custom-errors)
to more accurately describe what the validator is doing; changed from
`name_must_contain_space` to ` value_must_equal_bar`, #3327 by @michaelrios28
* Add `AmqpDsn` class, #3254 by @kludex
* Always use `Enum` value as default in generated JSON schema, #3190 by
@joaommartins
@@ -215,7 +237,7 @@
just as when sourced from environment variables, #2917 by @davidmreed
* add a dark mode to _pydantic_ documentation, #2913 by @gbdlin
* Make `pydantic-mypy` plugin compatible with `pyproject.toml` configuration,
consistent with `mypy` changes.
- See the
[doc](https://pydantic-docs.helpmanual.io/mypy_plugin/#configuring-the-plugin)
for more information, #2908 by @jrwalk
+ See the [doc](https://docs.pydantic.dev/mypy_plugin/#configuring-the-plugin)
for more information, #2908 by @jrwalk
* add Python 3.10 support, #2885 by @PrettyWood
* Correctly parse generic models with `Json[T]`, #2860 by @geekingfrog
* Update contrib docs re: Python version to use for building docs, #2856 by
@paxcodes
@@ -260,7 +282,7 @@
* Support generating schema for `Generic` fields with subtypes, #2375 by
@maximberg
* fix(encoder): serialize `NameEmail` to str, #2341 by @alecgerona
* add `Config.smart_union` to prevent coercion in `Union` if possible, see
- [the
doc](https://pydantic-docs.helpmanual.io/usage/model_config/#smart-union) for
more information, #2092 by @PrettyWood
+ [the doc](https://docs.pydantic.dev/usage/model_config/#smart-union) for more
information, #2092 by @PrettyWood
* Add ability to use `typing.Counter` as a model field type, #2060 by @uriyyo
* Add parameterised subclasses to `__bases__` when constructing new
parameterised classes, so that `A <: B => A[int] <: B[int]`, #2007 by
@diabolo-dan
* Create `FileUrl` type that allows URLs that conform to [RFC
8089](https://tools.ietf.org/html/rfc8089#section-2).
@@ -310,10 +332,10 @@
### Highlights
-* [Hypothesis plugin](https://pydantic-docs.helpmanual.io/hypothesis_plugin/)
for testing, #2097 by @Zac-HD
-* support for [`NamedTuple` and
`TypedDict`](https://pydantic-docs.helpmanual.io/usage/types/#annotated-types),
#2216 by @PrettyWood
-* Support [`Annotated` hints on model
fields](https://pydantic-docs.helpmanual.io/usage/schema/#typingannotated-fields),
#2147 by @JacobHayes
-* [`frozen` parameter on
`Config`](https://pydantic-docs.helpmanual.io/usage/model_config/) to allow
models to be hashed, #1880 by @rhuille
+* [Hypothesis plugin](https://docs.pydantic.dev/hypothesis_plugin/) for
testing, #2097 by @Zac-HD
+* support for [`NamedTuple` and
`TypedDict`](https://docs.pydantic.dev/usage/types/#annotated-types), #2216 by
@PrettyWood
+* Support [`Annotated` hints on model
fields](https://docs.pydantic.dev/usage/schema/#typingannotated-fields), #2147
by @JacobHayes
+* [`frozen` parameter on
`Config`](https://docs.pydantic.dev/usage/model_config/) to allow models to be
hashed, #1880 by @rhuille
### Changes
@@ -370,7 +392,7 @@
to validate parameters without actually calling the function, #2127 by
@PrettyWood
* Add the ability to customize settings sources (add / disable / change
priority order), #2107 by @kozlek
* Fix mypy complaints about most custom _pydantic_ types, #2098 by @PrettyWood
-* Add a [Hypothesis](https://hypothesis.readthedocs.io/) plugin for easier
[property-based
testing](https://increment.com/testing/in-praise-of-property-based-testing/)
with Pydantic's custom types - [usage details
here](https://pydantic-docs.helpmanual.io/hypothesis_plugin/), #2097 by @Zac-HD
+* Add a [Hypothesis](https://hypothesis.readthedocs.io/) plugin for easier
[property-based
testing](https://increment.com/testing/in-praise-of-property-based-testing/)
with Pydantic's custom types - [usage details
here](https://docs.pydantic.dev/hypothesis_plugin/), #2097 by @Zac-HD
* add validator for `None`, `NoneType` or `Literal[None]`, #2095 by @PrettyWood
* Handle properly fields of type `Callable` with a default value, #2094 by
@PrettyWood
* Updated `create_model` return type annotation to return type which inherits
from `__base__` argument, #2071 by @uriyyo
@@ -440,9 +462,9 @@
### Highlights
* Python 3.9 support, thanks @PrettyWood
-* [Private model
attributes](https://pydantic-docs.helpmanual.io/usage/models/#private-model-attributes),
thanks @Bobronium
-* ["secrets files" support in
`BaseSettings`](https://pydantic-docs.helpmanual.io/usage/settings/#secret-support),
thanks @mdgilene
-* [convert stdlib dataclasses to pydantic dataclasses and use stdlib
dataclasses in
models](https://pydantic-docs.helpmanual.io/usage/dataclasses/#stdlib-dataclasses-and-pydantic-dataclasses),
thanks @PrettyWood
+* [Private model
attributes](https://docs.pydantic.dev/usage/models/#private-model-attributes),
thanks @Bobronium
+* ["secrets files" support in
`BaseSettings`](https://docs.pydantic.dev/usage/settings/#secret-support),
thanks @mdgilene
+* [convert stdlib dataclasses to pydantic dataclasses and use stdlib
dataclasses in
models](https://docs.pydantic.dev/usage/dataclasses/#stdlib-dataclasses-and-pydantic-dataclasses),
thanks @PrettyWood
### Changes
@@ -585,7 +607,7 @@
* **Breaking Change:** alias precedence logic changed so aliases on a field
always take priority over
an alias from `alias_generator` to avoid buggy/unexpected behaviour,
- see
[here](https://pydantic-docs.helpmanual.io/usage/model_config/#alias-precedence)
for details, #1178 by @samuelcolvin
+ see [here](https://docs.pydantic.dev/usage/model_config/#alias-precedence)
for details, #1178 by @samuelcolvin
* Add support for unicode and punycode in TLDs, #1182 by @jamescurtin
* Fix `cls` argument in validators during assignment, #1172 by @samuelcolvin
* completing Luhn algorithm for `PaymentCardNumber`, #1166 by @cuencandres
@@ -627,7 +649,7 @@
* **Possible Breaking Change:** Add support for required `Optional` with
`name: Optional[AnyType] = Field(...)`
and refactor `ModelField` creation to preserve `required` parameter value,
#1031 by @tiangolo;
- see
[here](https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields)
for details
+ see [here](https://docs.pydantic.dev/usage/models/#required-optional-fields)
for details
* Add benchmarks for `cattrs`, #513 by @sebastianmika
* Add `exclude_none` option to `dict()` and friends, #587 by @niknetniko
* Add benchmarks for `valideer`, #670 by @gsakkis
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/Makefile new/pydantic-1.10.4/Makefile
--- old/pydantic-1.10.2/Makefile 2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/Makefile 2022-12-30 10:53:51.000000000 +0100
@@ -124,9 +124,3 @@
docs-serve:
python docs/build/main.py
mkdocs serve
-
-.PHONY: publish-docs
-publish-docs:
- zip -r site.zip site
- @curl -H "Content-Type: application/zip" -H "Authorization: Bearer
${NETLIFY}" \
- --data-binary "@site.zip"
https://api.netlify.com/api/v1/sites/pydantic-docs.netlify.com/deploys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/README.md
new/pydantic-1.10.4/README.md
--- old/pydantic-1.10.2/README.md 2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/README.md 2022-12-30 10:53:51.000000000 +0100
@@ -15,13 +15,13 @@
## Help
-See [documentation](https://pydantic-docs.helpmanual.io/) for more details.
+See [documentation](https://docs.pydantic.dev/) for more details.
## Installation
Install using `pip install -U pydantic` or `conda install pydantic -c
conda-forge`.
For more installation options to make *pydantic* even faster,
-see the [Install](https://pydantic-docs.helpmanual.io/install/) section in the
documentation.
+see the [Install](https://docs.pydantic.dev/install/) section in the
documentation.
## A Simple Example
@@ -48,7 +48,7 @@
For guidance on setting up a development environment and how to make a
contribution to *pydantic*, see
-[Contributing to Pydantic](https://pydantic-docs.helpmanual.io/contributing/).
+[Contributing to Pydantic](https://docs.pydantic.dev/contributing/).
## Reporting a Security Vulnerability
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/blog/pydantic-v2.md
new/pydantic-1.10.4/docs/blog/pydantic-v2.md
--- old/pydantic-1.10.2/docs/blog/pydantic-v2.md 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/blog/pydantic-v2.md 2022-12-30
10:53:51.000000000 +0100
@@ -15,6 +15,10 @@
Updated late 10 Jul 2022, see
[pydantic#4226](https://github.com/pydantic/pydantic/pull/4226).
+Update 30 Dec 2022: **The new release deadline for Pydantic V2 is the end of
Q1 2023**,
+see [pydantic#4887](https://github.com/pydantic/pydantic/issues/4887) for more
details, futher updates
+will be posted on that issue.
+
---
I've spoken to quite a few people about pydantic V2, and mention it in passing
even more.
@@ -123,7 +127,7 @@
pydantic-core is usable now, albeit with an unintuitive API, if you're
interested, please give it a try.
pydantic-core provides validators for common data types,
-[see a list
here](https://github.com/pydantic/pydantic-core/blob/main/pydantic_core/_types.py#L291).
+[see a list
here](https://github.com/pydantic/pydantic-core/blob/main/pydantic_core/schema_types.py#L314).
Other, less commonly used data types will be supported via validator functions
implemented in pydantic, in Python.
See [pydantic-core#153](https://github.com/pydantic/pydantic-core/issues/153)
@@ -639,7 +643,7 @@
Since the core structure of validators has changed from "a list of validators
to call one after another" to
"a tree of validators which call each other", the
-[`__get_validators__`](https://pydantic-docs.helpmanual.io/usage/types/#classes-with-__get_validators__)
+[`__get_validators__`](https://docs.pydantic.dev/usage/types/#classes-with-__get_validators__)
way of defining custom field types no longer makes sense.
Instead, we'll look for the attribute `__pydantic_validation_schema__` which
must be a
@@ -745,7 +749,7 @@
specific need to keep the type, you can use wrap validators or custom type
validation as described above
6. integers are represented in rust code as `i64`, meaning if you want to use
ints where `abs(v) > 2^63 â 1`
(9,223,372,036,854,775,807), you'll need to use a [wrap
validator](#validator-function-improvements) and your own logic
-7. [Settings Management](https://pydantic-docs.helpmanual.io/usage/settings/)
??? - I definitely don't want to
+7. [Settings Management](https://docs.pydantic.dev/usage/settings/) ??? - I
definitely don't want to
remove the functionality, but it's something of a historical curiosity that
it lives within pydantic,
perhaps it should move to a separate package, perhaps installable alongside
pydantic with
`pip install pydantic[settings]`?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/build/exec_examples.py
new/pydantic-1.10.4/docs/build/exec_examples.py
--- old/pydantic-1.10.2/docs/build/exec_examples.py 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/build/exec_examples.py 2022-12-30
10:53:51.000000000 +0100
@@ -40,11 +40,12 @@
```
""".strip()
JSON_OUTPUT_MD_TMPL = """
+
Outputs:
```json
{output}
```
-""".strip()
+"""
def to_string(value: Any) -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/build/main.py
new/pydantic-1.10.4/docs/build/main.py
--- old/pydantic-1.10.2/docs/build/main.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/docs/build/main.py 2022-12-30 10:53:51.000000000
+0100
@@ -10,7 +10,7 @@
def main() -> int:
history = (PROJECT_ROOT / 'HISTORY.md').read_text()
- history = re.sub(r'#(\d+)',
r'[#\1](https://github.com/pydantic/pydantic/issues/\1)', history)
+ history = re.sub(r'(\s)#(\d+)',
r'\1[#\2](https://github.com/pydantic/pydantic/issues/\2)', history)
history = re.sub(r'(\s)@([\w\-]+)', r'\1[@\2](https://github.com/\2)',
history, flags=re.I)
history = re.sub('@@', '@', history)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic-1.10.2/docs/examples/models_orm_mode_reserved_name.py
new/pydantic-1.10.4/docs/examples/models_orm_mode_reserved_name.py
--- old/pydantic-1.10.2/docs/examples/models_orm_mode_reserved_name.py
2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/examples/models_orm_mode_reserved_name.py
2022-12-30 10:53:51.000000000 +0100
@@ -12,10 +12,10 @@
orm_mode = True
-BaseModel = declarative_base()
+Base = declarative_base()
-class SQLModel(BaseModel):
+class SQLModel(Base):
__tablename__ = 'my_table'
id = sa.Column('id', sa.Integer, primary_key=True)
# 'metadata' is reserved by SQLAlchemy, hence the '_'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic-1.10.2/docs/examples/postponed_annotations_broken.py
new/pydantic-1.10.4/docs/examples/postponed_annotations_broken.py
--- old/pydantic-1.10.2/docs/examples/postponed_annotations_broken.py
2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/examples/postponed_annotations_broken.py
2022-12-30 10:53:51.000000000 +0100
@@ -4,7 +4,7 @@
def this_is_broken():
- from pydantic import HttpUrl # HttpUrl is defined in functuon local scope
+ from pydantic import HttpUrl # HttpUrl is defined in function local scope
class Model(BaseModel):
a: HttpUrl
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/examples/schema_with_field.py
new/pydantic-1.10.4/docs/examples/schema_with_field.py
--- old/pydantic-1.10.2/docs/examples/schema_with_field.py 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/examples/schema_with_field.py 2022-12-30
10:53:51.000000000 +0100
@@ -1,5 +1,5 @@
# output-json
-from typing import Optional
+from typing import Any, Callable, Dict, Generator, Optional
from pydantic import BaseModel, Field
from pydantic.fields import ModelField
@@ -7,18 +7,20 @@
class RestrictedAlphabetStr(str):
@classmethod
- def __get_validators__(cls):
+ def __get_validators__(cls) -> Generator[Callable, None, None]:
yield cls.validate
@classmethod
- def validate(cls, value, field: ModelField):
+ def validate(cls, value: str, field: ModelField):
alphabet = field.field_info.extra['alphabet']
if any(c not in alphabet for c in value):
raise ValueError(f'{value!r} is not restricted to {alphabet!r}')
return cls(value)
@classmethod
- def __modify_schema__(cls, field_schema, field: Optional[ModelField]):
+ def __modify_schema__(
+ cls, field_schema: Dict[str, Any], field: Optional[ModelField]
+ ):
if field:
alphabet = field.field_info.extra['alphabet']
field_schema['examples'] = [c * 3 for c in alphabet]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/extra/tweaks.css
new/pydantic-1.10.4/docs/extra/tweaks.css
--- old/pydantic-1.10.2/docs/extra/tweaks.css 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/docs/extra/tweaks.css 2022-12-30 10:53:51.000000000
+0100
@@ -24,7 +24,7 @@
.sponsors > div {
text-align: center;
- width: 25%;
+ width: 33%;
padding-bottom: 20px;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/index.md
new/pydantic-1.10.4/docs/index.md
--- old/pydantic-1.10.2/docs/index.md 2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/index.md 2022-12-30 10:53:51.000000000 +0100
@@ -66,6 +66,12 @@
<span>SendCloud</span>
</a>
</div>
+ <div>
+ <a rel="sponsored" target="_blank" href="https://jina.ai">
+ <img src="./sponsor_logos/jina-ai.png" alt="Jina AI" />
+ <span>Jina AI</span>
+ </a>
+ </div>
</div>
And many more who kindly sponsor Samuel Colvin on [GitHub
Sponsors](https://github.com/sponsors/samuelcolvin#sponsors).
Binary files old/pydantic-1.10.2/docs/sponsor_logos/jina-ai.png and
new/pydantic-1.10.4/docs/sponsor_logos/jina-ai.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/usage/model_config.md
new/pydantic-1.10.4/docs/usage/model_config.md
--- old/pydantic-1.10.2/docs/usage/model_config.md 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/usage/model_config.md 2022-12-30
10:53:51.000000000 +0100
@@ -55,7 +55,7 @@
**`fields`**
: a `dict` containing schema information for each field; this is equivalent to
using [the `Field` class](schema.md), except when a field is already
- defined trough annotation or the Field class, in which case only
+ defined through annotation or the Field class, in which case only
`alias`, `include`, `exclude`, `min_length`, `max_length`, `regex`, `gt`,
`lt`, `gt`, `le`,
`multiple_of`, `max_digits`, `decimal_places`, `min_items`, `max_items`,
`unique_items`
and allow_mutation can be set (for example you cannot set default of
default_factory)
@@ -127,7 +127,7 @@
or after (value `'after_validation'`) parsing and validation when they are
[converted](dataclasses.md#stdlib-dataclasses-and-_pydantic_-dataclasses).
**`allow_inf_nan`**
-: whether to allows infinity (`+inf` an `-inf`) and NaN values to float
fields, defaults to `True`,
+: whether to allow infinity (`+inf` an `-inf`) and NaN values to float fields,
defaults to `True`,
set to `False` for compatibility with `JSON`,
see [#3994](https://github.com/pydantic/pydantic/pull/3994) for more
details, added in **V1.10**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/usage/models.md
new/pydantic-1.10.4/docs/usage/models.md
--- old/pydantic-1.10.2/docs/usage/models.md 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/docs/usage/models.md 2022-12-30 10:53:51.000000000
+0100
@@ -435,7 +435,7 @@
{!.tmp_examples/models_required_fields.md!}
-Where `Field` refers to the [field function](schema.md#field-customisation).
+Where `Field` refers to the [field function](schema.md#field-customization).
Here `a`, `b` and `c` are all required. However, use of the ellipses in `b`
will not work well
with [mypy](mypy.md), and as of **v1.0** should be avoided in most cases.
@@ -471,7 +471,7 @@
{!.tmp_examples/models_default_factory.md!}
-Where `Field` refers to the [field function](schema.md#field-customisation).
+Where `Field` refers to the [field function](schema.md#field-customization).
!!! warning
The `default_factory` expects the field type to be set.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/usage/schema.md
new/pydantic-1.10.4/docs/usage/schema.md
--- old/pydantic-1.10.2/docs/usage/schema.md 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/docs/usage/schema.md 2022-12-30 10:53:51.000000000
+0100
@@ -190,7 +190,3 @@
For example, the `title` key can be removed from the model's `properties`:
{!.tmp_examples/schema_extra_callable.md!}
-
-
-
-```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/usage/types.md
new/pydantic-1.10.4/docs/usage/types.md
--- old/pydantic-1.10.2/docs/usage/types.md 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/docs/usage/types.md 2022-12-30 10:53:51.000000000
+0100
@@ -310,7 +310,7 @@
* `int` or `float`, assumed as Unix time, i.e. seconds (if >= `-2e10` or <=
`2e10`) or milliseconds (if < `-2e10`or > `2e10`) since 1 January 1970
* `str`, following formats work:
- * `YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]`
+ * `YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]`
* `int` or `float` as a string (assumed as Unix time)
* `date` fields can be:
@@ -327,7 +327,7 @@
* `time`, existing `time` object
* `str`, following formats work:
- * `HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]`
+ * `HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]`
* `timedelta` fields can be:
@@ -490,7 +490,7 @@
`CockroachDsn`
: a cockroachdb DSN style URL; see [URLs](#urls)
-`RabbitMqDsn`
+`AmqpDsn`
: an `AMQP` DSN style URL as used by RabbitMQ, StormMQ, ActiveMQ etc.; see
[URLs](#urls)
`RedisDsn`
@@ -598,6 +598,7 @@
- `postgresql`
- `postgresql+asyncpg`
- `postgresql+pg8000`
+ - `postgresql+psycopg`
- `postgresql+psycopg2`
- `postgresql+psycopg2cffi`
- `postgresql+py-postgresql`
@@ -606,9 +607,9 @@
- `cockroachdb+asyncpg`
- `cockroachdb+psycopg2`
- `AmqpDsn`: schema `amqp` or `amqps`, user info not required, TLD not
required, host not required
-- `RedisDsn`: scheme `redis` or `rediss`, user info not required, tld not
required, host not required (CHANGED: user info
+- `RedisDsn`: scheme `redis` or `rediss`, user info not required, tld not
required, host not required (CHANGED: user info) (e.g.,
`rediss://:pass@localhost`)
- `MongoDsn` : scheme `mongodb`, user info not required, database name not
required, port
- not required from **v1.6** onwards), user info may be passed without user
part (e.g., `rediss://:pass@localhost`)
+ not required from **v1.6** onwards), user info may be passed without user
part (e.g., `mongodb://mongodb0.example.com:27017`)
- `stricturl`: method with the following keyword arguments:
- `strip_whitespace: bool = True`
- `min_length: int = 1`
@@ -780,7 +781,7 @@
{!.tmp_examples/types_constrained.md!}
-Where `Field` refers to the [field function](schema.md#field-customisation).
+Where `Field` refers to the [field function](schema.md#field-customization).
### Arguments to `conlist`
The following arguments are available when using the `conlist` type function
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/docs/usage/validation_decorator.md
new/pydantic-1.10.4/docs/usage/validation_decorator.md
--- old/pydantic-1.10.2/docs/usage/validation_decorator.md 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/docs/usage/validation_decorator.md 2022-12-30
10:53:51.000000000 +0100
@@ -48,14 +48,14 @@
## Using Field to describe function arguments
-[Field](schema.md#field-customisation) can also be used with
`validate_arguments` to provide extra information about
+[Field](schema.md#field-customization) can also be used with
`validate_arguments` to provide extra information about
the field and validations. In general it should be used in a type hint with
[Annotated](schema.md#typingannotated-fields), unless `default_factory` is
specified, in which case it should be used
as the default value of the field:
{!.tmp_examples/validation_decorator_field.md!}
-The [alias](model_config#alias-precedence) can be used with the decorator as
normal.
+The [alias](model_config.md#alias-precedence) can be used with the decorator
as normal.
{!.tmp_examples/validation_decorator_field_alias.md!}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/mkdocs.yml
new/pydantic-1.10.4/mkdocs.yml
--- old/pydantic-1.10.2/mkdocs.yml 2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/mkdocs.yml 2022-12-30 10:53:51.000000000 +0100
@@ -1,7 +1,7 @@
site_name: pydantic
site_description: Data validation and settings management using Python type
hints
strict: true
-site_url: https://pydantic-docs.helpmanual.io/
+site_url: https://docs.pydantic.dev/
theme:
name: 'material'
@@ -28,6 +28,7 @@
repo_name: pydantic/pydantic
repo_url: https://github.com/pydantic/pydantic
+edit_uri: edit/main/docs/
extra:
analytics:
provider: google
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/_hypothesis_plugin.py
new/pydantic-1.10.4/pydantic/_hypothesis_plugin.py
--- old/pydantic-1.10.2/pydantic/_hypothesis_plugin.py 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/pydantic/_hypothesis_plugin.py 2022-12-30
10:53:51.000000000 +0100
@@ -10,7 +10,7 @@
https://hypothesis.readthedocs.io/en/latest/strategies.html#registering-strategies-via-setuptools-entry-points
https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.register_type_strategy
https://hypothesis.readthedocs.io/en/latest/strategies.html#interaction-with-pytest-cov
-https://pydantic-docs.helpmanual.io/usage/types/#pydantic-types
+https://docs.pydantic.dev/usage/types/#pydantic-types
Note that because our motivation is to *improve user experience*, the
strategies
are always sound (never generate invalid data) but sacrifice completeness for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/config.py
new/pydantic-1.10.4/pydantic/config.py
--- old/pydantic-1.10.2/pydantic/config.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/config.py 2022-12-30 10:53:51.000000000
+0100
@@ -68,9 +68,7 @@
json_encoders: Dict[Type[object], AnyCallable]
underscore_attrs_are_private: bool
allow_inf_nan: bool
-
- # whether or not inherited models as fields should be reconstructed as
base model
- copy_on_model_validation: bool
+ copy_on_model_validation: Literal['none', 'deep', 'shallow']
# whether dataclass `__post_init__` should be run after validation
post_init_call: Literal['before_validation', 'after_validation']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/dataclasses.py
new/pydantic-1.10.4/pydantic/dataclasses.py
--- old/pydantic-1.10.2/pydantic/dataclasses.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/dataclasses.py 2022-12-30 10:53:51.000000000
+0100
@@ -34,20 +34,7 @@
import sys
from contextlib import contextmanager
from functools import wraps
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- ClassVar,
- Dict,
- Generator,
- Optional,
- Set,
- Type,
- TypeVar,
- Union,
- overload,
-)
+from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, Generator,
Optional, Type, TypeVar, Union, overload
from typing_extensions import dataclass_transform
@@ -105,7 +92,7 @@
if sys.version_info >= (3, 10):
- @dataclass_transform(kw_only_default=True, field_descriptors=(Field,
FieldInfo))
+ @dataclass_transform(kw_only_default=True, field_specifiers=(Field,
FieldInfo))
@overload
def dataclass(
*,
@@ -117,11 +104,12 @@
frozen: bool = False,
config: Union[ConfigDict, Type[object], None] = None,
validate_on_init: Optional[bool] = None,
+ use_proxy: Optional[bool] = None,
kw_only: bool = ...,
) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']:
...
- @dataclass_transform(kw_only_default=True, field_descriptors=(Field,
FieldInfo))
+ @dataclass_transform(kw_only_default=True, field_specifiers=(Field,
FieldInfo))
@overload
def dataclass(
_cls: Type[_T],
@@ -134,13 +122,14 @@
frozen: bool = False,
config: Union[ConfigDict, Type[object], None] = None,
validate_on_init: Optional[bool] = None,
+ use_proxy: Optional[bool] = None,
kw_only: bool = ...,
) -> 'DataclassClassOrWrapper':
...
else:
- @dataclass_transform(kw_only_default=True, field_descriptors=(Field,
FieldInfo))
+ @dataclass_transform(kw_only_default=True, field_specifiers=(Field,
FieldInfo))
@overload
def dataclass(
*,
@@ -152,10 +141,11 @@
frozen: bool = False,
config: Union[ConfigDict, Type[object], None] = None,
validate_on_init: Optional[bool] = None,
+ use_proxy: Optional[bool] = None,
) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']:
...
- @dataclass_transform(kw_only_default=True, field_descriptors=(Field,
FieldInfo))
+ @dataclass_transform(kw_only_default=True, field_specifiers=(Field,
FieldInfo))
@overload
def dataclass(
_cls: Type[_T],
@@ -168,11 +158,12 @@
frozen: bool = False,
config: Union[ConfigDict, Type[object], None] = None,
validate_on_init: Optional[bool] = None,
+ use_proxy: Optional[bool] = None,
) -> 'DataclassClassOrWrapper':
...
-@dataclass_transform(kw_only_default=True, field_descriptors=(Field,
FieldInfo))
+@dataclass_transform(kw_only_default=True, field_specifiers=(Field, FieldInfo))
def dataclass(
_cls: Optional[Type[_T]] = None,
*,
@@ -184,6 +175,7 @@
frozen: bool = False,
config: Union[ConfigDict, Type[object], None] = None,
validate_on_init: Optional[bool] = None,
+ use_proxy: Optional[bool] = None,
kw_only: bool = False,
) -> Union[Callable[[Type[_T]], 'DataclassClassOrWrapper'],
'DataclassClassOrWrapper']:
"""
@@ -197,7 +189,15 @@
def wrap(cls: Type[Any]) -> 'DataclassClassOrWrapper':
import dataclasses
- if is_builtin_dataclass(cls) and _extra_dc_args(_cls) ==
_extra_dc_args(_cls.__bases__[0]): # type: ignore
+ should_use_proxy = (
+ use_proxy
+ if use_proxy is not None
+ else (
+ is_builtin_dataclass(cls)
+ and (cls.__bases__[0] is object or set(dir(cls)) ==
set(dir(cls.__bases__[0])))
+ )
+ )
+ if should_use_proxy:
dc_cls_doc = ''
dc_cls = DataclassProxy(cls)
default_validate_on_init = False
@@ -254,6 +254,9 @@
def __getattr__(self, name: str) -> Any:
return getattr(self.__dataclass__, name)
+ def __setattr__(self, __name: str, __value: Any) -> None:
+ return setattr(self.__dataclass__, __name, __value)
+
def __instancecheck__(self, instance: Any) -> bool:
return isinstance(instance, self.__dataclass__)
@@ -285,7 +288,10 @@
init(self, *args, **kwargs)
if hasattr(dc_cls, '__post_init__'):
- post_init = dc_cls.__post_init__
+ try:
+ post_init = dc_cls.__post_init__.__wrapped__ # type:
ignore[attr-defined]
+ except AttributeError:
+ post_init = dc_cls.__post_init__
@wraps(post_init)
def new_post_init(self: 'Dataclass', *args: Any, **kwargs: Any) ->
None:
@@ -431,14 +437,6 @@
object.__setattr__(self, name, value)
-def _extra_dc_args(cls: Type[Any]) -> Set[str]:
- return {
- x
- for x in dir(cls)
- if x not in getattr(cls, '__dataclass_fields__', {}) and not
(x.startswith('__') and x.endswith('__'))
- }
-
-
def is_builtin_dataclass(_cls: Type[Any]) -> bool:
"""
Whether a class is a stdlib dataclass
@@ -476,4 +474,4 @@
and yield the validators
It retrieves the parameters of the dataclass and forwards them to the
newly created dataclass
"""
- yield from _get_validators(dataclass(dc_cls, config=config,
validate_on_init=False))
+ yield from _get_validators(dataclass(dc_cls, config=config,
use_proxy=True))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/generics.py
new/pydantic-1.10.4/pydantic/generics.py
--- old/pydantic-1.10.2/pydantic/generics.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/generics.py 2022-12-30 10:53:51.000000000
+0100
@@ -64,7 +64,11 @@
"""
def _cache_key(_params: Any) -> Tuple[Type[GenericModelT], Any,
Tuple[Any, ...]]:
- return cls, _params, get_args(_params)
+ args = get_args(_params)
+ # python returns a list for Callables, which is not hashable
+ if len(args) == 2 and isinstance(args[0], list):
+ args = (tuple(args[0]), args[1])
+ return cls, _params, args
cached = _generic_types_cache.get(_cache_key(params))
if cached is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/main.py
new/pydantic-1.10.4/pydantic/main.py
--- old/pydantic-1.10.2/pydantic/main.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/main.py 2022-12-30 10:53:51.000000000
+0100
@@ -118,7 +118,7 @@
_is_base_model_class_defined = False
-@dataclass_transform(kw_only_default=True, field_descriptors=(Field,
FieldInfo))
+@dataclass_transform(kw_only_default=True, field_specifiers=(Field, FieldInfo))
class ModelMetaclass(ABCMeta):
@no_type_check # noqa C901
def __new__(mcs, name, bases, namespace, **kwargs): # noqa C901
@@ -508,6 +508,7 @@
def _enforce_dict_if_root(cls, obj: Any) -> Any:
if cls.__custom_root_type__ and (
not (isinstance(obj, dict) and obj.keys() == {ROOT_KEY})
+ and not (isinstance(obj, BaseModel) and obj.__fields__.keys() ==
{ROOT_KEY})
or cls.__fields__[ROOT_KEY].shape in MAPPING_LIKE_SHAPES
):
return {ROOT_KEY: obj}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/networks.py
new/pydantic-1.10.4/pydantic/networks.py
--- old/pydantic-1.10.2/pydantic/networks.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/networks.py 2022-12-30 10:53:51.000000000
+0100
@@ -490,6 +490,7 @@
'postgresql',
'postgresql+asyncpg',
'postgresql+pg8000',
+ 'postgresql+psycopg',
'postgresql+psycopg2',
'postgresql+psycopg2cffi',
'postgresql+py-postgresql',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/schema.py
new/pydantic-1.10.4/pydantic/schema.py
--- old/pydantic-1.10.2/pydantic/schema.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/schema.py 2022-12-30 10:53:51.000000000
+0100
@@ -1,6 +1,7 @@
import re
import warnings
from collections import defaultdict
+from dataclasses import is_dataclass
from datetime import date, datetime, time, timedelta
from decimal import Decimal
from enum import Enum
@@ -490,7 +491,7 @@
# Dict keys have a regex pattern
# items_schema might be a schema or empty dict, add it either way
f_schema['patternProperties'] = {regex.pattern: items_schema}
- elif items_schema:
+ if items_schema:
# The dict values are not simply Any, so they need a schema
f_schema['additionalProperties'] = items_schema
elif field.shape == SHAPE_TUPLE or (field.shape == SHAPE_GENERIC and not
issubclass(field.type_, BaseModel)):
@@ -657,11 +658,13 @@
This is similar to the `model_process_schema` function, but applies to
``Enum`` objects.
"""
+ import inspect
+
schema_: Dict[str, Any] = {
'title': enum.__name__,
# Python assigns all enums a default docstring value of 'An
enumeration', so
# all enums will have a description field even if not explicitly
provided.
- 'description': enum.__doc__ or 'An enumeration.',
+ 'description': inspect.cleandoc(enum.__doc__ or 'An enumeration.'),
# Add enum values and the enum field type to the schema.
'enum': [item.value for item in cast(Iterable[Enum], enum)],
}
@@ -969,7 +972,14 @@
def encode_default(dft: Any) -> Any:
- if isinstance(dft, Enum):
+ from .main import BaseModel
+
+ if isinstance(dft, BaseModel) or is_dataclass(dft):
+ dft = cast('dict[str, Any]', pydantic_encoder(dft))
+
+ if isinstance(dft, dict):
+ return {encode_default(k): encode_default(v) for k, v in dft.items()}
+ elif isinstance(dft, Enum):
return dft.value
elif isinstance(dft, (int, float, str)):
return dft
@@ -977,8 +987,6 @@
t = dft.__class__
seq_args = (encode_default(v) for v in dft)
return t(*seq_args) if is_namedtuple(t) else t(seq_args)
- elif isinstance(dft, dict):
- return {encode_default(k): encode_default(v) for k, v in dft.items()}
elif dft is None:
return None
else:
@@ -1011,7 +1019,7 @@
raise ValueError(
f'On field "{field_name}" the following field constraints are set
but not enforced: '
f'{", ".join(unused_constraints)}. '
- f'\nFor more details see
https://pydantic-docs.helpmanual.io/usage/schema/#unenforced-field-constraints'
+ f'\nFor more details see
https://docs.pydantic.dev/usage/schema/#unenforced-field-constraints'
)
return annotation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/types.py
new/pydantic-1.10.4/pydantic/types.py
--- old/pydantic-1.10.2/pydantic/types.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/types.py 2022-12-30 10:53:51.000000000
+0100
@@ -403,7 +403,7 @@
min_length: OptionalInt = None
max_length: OptionalInt = None
curtail_length: OptionalInt = None
- regex: Optional[Pattern[str]] = None
+ regex: Optional[Union[str, Pattern[str]]] = None
strict = False
@classmethod
@@ -412,7 +412,7 @@
field_schema,
minLength=cls.min_length,
maxLength=cls.max_length,
- pattern=cls.regex and cls.regex.pattern,
+ pattern=cls.regex and cls._get_pattern(cls.regex),
)
@classmethod
@@ -430,11 +430,15 @@
value = value[: cls.curtail_length]
if cls.regex:
- if not cls.regex.match(value):
- raise errors.StrRegexError(pattern=cls.regex.pattern)
+ if not re.match(cls.regex, value):
+ raise errors.StrRegexError(pattern=cls._get_pattern(cls.regex))
return value
+ @staticmethod
+ def _get_pattern(regex: Union[str, Pattern[str]]) -> str:
+ return regex if isinstance(regex, str) else regex.pattern
+
def constr(
*,
@@ -595,7 +599,10 @@
return v
@classmethod
- def unique_items_validator(cls, v: 'List[T]') -> 'List[T]':
+ def unique_items_validator(cls, v: 'Optional[List[T]]') ->
'Optional[List[T]]':
+ if v is None:
+ return None
+
for i, value in enumerate(v, start=1):
if value in v[i:]:
raise errors.ListUniqueItemsError()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/pydantic/version.py
new/pydantic-1.10.4/pydantic/version.py
--- old/pydantic-1.10.2/pydantic/version.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/pydantic/version.py 2022-12-30 10:53:51.000000000
+0100
@@ -1,6 +1,6 @@
__all__ = 'compiled', 'VERSION', 'version_info'
-VERSION = '1.10.2'
+VERSION = '1.10.4'
try:
import cython # type: ignore
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/setup.py new/pydantic-1.10.4/setup.py
--- old/pydantic-1.10.2/setup.py 2022-09-05 18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/setup.py 2022-12-30 10:53:51.000000000 +0100
@@ -60,7 +60,7 @@
THIS_DIR = Path(__file__).resolve().parent
try:
history = (THIS_DIR / 'HISTORY.md').read_text(encoding='utf-8')
- history = re.sub(r'#(\d+)',
r'[#\1](https://github.com/pydantic/pydantic/issues/\1)', history)
+ history = re.sub(r'(\s)#(\d+)',
r'\1[#\2](https://github.com/pydantic/pydantic/issues/\2)', history)
history = re.sub(r'( +)@([\w\-]+)', r'\1[@\2](https://github.com/\2)',
history, flags=re.I)
history = re.sub('@@', '@', history)
@@ -82,9 +82,9 @@
compiler_directives = {}
if 'CYTHON_TRACE' in sys.argv:
compiler_directives['linetrace'] = True
- # Set CFLAG to all optimizations (-O3)
+ # Set CFLAG to all optimizations (-O3), add `-g0` to reduce size of
binaries, see #2276
# Any additional CFLAGS will be appended. Only the last optimization
flag will have effect
- os.environ['CFLAGS'] = '-O3 ' + os.environ.get('CFLAGS', '')
+ os.environ['CFLAGS'] = '-O3 -g0 ' + os.environ.get('CFLAGS', '')
ext_modules = cythonize(
'pydantic/*.py',
exclude=['pydantic/generics.py'],
@@ -130,7 +130,7 @@
python_requires='>=3.7',
zip_safe=False, #
https://mypy.readthedocs.io/en/latest/installed_packages.html
install_requires=[
- 'typing-extensions>=4.1.0'
+ 'typing-extensions>=4.2.0'
],
extras_require={
'email': ['email-validator>=1.0.3'],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/requirements-testing.txt
new/pydantic-1.10.4/tests/requirements-testing.txt
--- old/pydantic-1.10.2/tests/requirements-testing.txt 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/tests/requirements-testing.txt 2022-12-30
10:53:51.000000000 +0100
@@ -7,3 +7,5 @@
pytest-cov==3.0.0
pytest-mock==3.8.2
pytest-sugar==0.9.5
+# pin typing-extensions to minimum requirement - see #4885
+typing-extensions==4.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_dataclasses.py
new/pydantic-1.10.4/tests/test_dataclasses.py
--- old/pydantic-1.10.2/tests/test_dataclasses.py 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/tests/test_dataclasses.py 2022-12-30
10:53:51.000000000 +0100
@@ -1472,3 +1472,139 @@
self.a *= 3
assert C().a == 6 # 1 * 3 + 3
+
+
+def test_inheritance_post_init_2():
+ post_init_calls = 0
+ post_init_post_parse_calls = 0
+
+ @pydantic.dataclasses.dataclass
+ class BaseClass:
+ def __post_init__(self):
+ nonlocal post_init_calls
+ post_init_calls += 1
+
+ @pydantic.dataclasses.dataclass
+ class AbstractClass(BaseClass):
+ pass
+
+ @pydantic.dataclasses.dataclass
+ class ConcreteClass(AbstractClass):
+ def __post_init_post_parse__(self):
+ nonlocal post_init_post_parse_calls
+ post_init_post_parse_calls += 1
+
+ ConcreteClass()
+ assert post_init_calls == 1
+ assert post_init_post_parse_calls == 1
+
+
+def test_dataclass_setattr():
+ class Foo:
+ bar: str = 'cat'
+
+ default_config = dataclasses.make_dataclass(
+ cls_name=Foo.__name__,
+ bases=(dataclasses.dataclass(Foo),),
+ fields=[('bar', ClassVar[str], dataclasses.field(default=Foo.bar))],
+ )
+
+ config = pydantic.dataclasses.dataclass(default_config)
+ assert config.bar == 'cat'
+ setattr(config, 'bar', 'dog')
+ assert config.bar == 'dog'
+
+
+def test_frozen_dataclasses():
+ @dataclasses.dataclass(frozen=True)
+ class First:
+ a: int
+
+ @dataclasses.dataclass(frozen=True)
+ class Second(First):
+ @property
+ def b(self):
+ return self.a
+
+ class My(BaseModel):
+ my: Second
+
+ assert My(my=Second(a='1')).my.b == 1
+
+
+def test_empty_dataclass():
+ """should be able to inherit without adding a field"""
+
+ @dataclasses.dataclass
+ class UnvalidatedDataclass:
+ a: int = 0
+
+ @pydantic.dataclasses.dataclass
+ class ValidatedDerivedA(UnvalidatedDataclass):
+ ...
+
+ @pydantic.dataclasses.dataclass()
+ class ValidatedDerivedB(UnvalidatedDataclass):
+ b: int = 0
+
+ @pydantic.dataclasses.dataclass()
+ class ValidatedDerivedC(UnvalidatedDataclass):
+ ...
+
+
+def test_proxy_dataclass():
+ @dataclasses.dataclass
+ class Foo:
+ a: Optional[int] = dataclasses.field(default=42)
+ b: List = dataclasses.field(default_factory=list)
+
+ @dataclasses.dataclass
+ class Bar:
+ pass
+
+ @dataclasses.dataclass
+ class Model1:
+ foo: Foo
+
+ class Model2(BaseModel):
+ foo: Foo
+
+ m1 = Model1(foo=Foo())
+ m2 = Model2(foo=Foo())
+
+ assert m1.foo.a == m2.foo.a == 42
+ assert m1.foo.b == m2.foo.b == []
+ assert m1.foo.Bar() is not None
+ assert m2.foo.Bar() is not None
+
+
+def test_proxy_dataclass_2():
+ @dataclasses.dataclass
+ class M1:
+ a: int
+ b: str = 'b'
+ c: float = dataclasses.field(init=False)
+
+ def __post_init__(self):
+ self.c = float(self.a)
+
+ @dataclasses.dataclass
+ class M2:
+ a: int
+ b: str = 'b'
+ c: float = dataclasses.field(init=False)
+
+ def __post_init__(self):
+ self.c = float(self.a)
+
+ @pydantic.validator('b')
+ def check_b(cls, v):
+ if not v:
+ raise ValueError('b should not be empty')
+ return v
+
+ m1 = pydantic.parse_obj_as(M1, {'a': 3})
+ m2 = pydantic.parse_obj_as(M2, {'a': 3})
+ assert m1.a == m2.a == 3
+ assert m1.b == m2.b == 'b'
+ assert m1.c == m2.c == 3.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_decorator.py
new/pydantic-1.10.4/tests/test_decorator.py
--- old/pydantic-1.10.2/tests/test_decorator.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/tests/test_decorator.py 2022-12-30 10:53:51.000000000
+0100
@@ -266,10 +266,9 @@
v = await foo(1, 2)
assert v == 'a=1 b=2'
- loop = asyncio.get_event_loop_policy().get_event_loop()
- loop.run_until_complete(run())
+ asyncio.run(run())
with pytest.raises(ValidationError) as exc_info:
- loop.run_until_complete(foo('x'))
+ asyncio.run(foo('x'))
assert exc_info.value.errors() == [{'loc': ('b',), 'msg': 'field
required', 'type': 'value_error.missing'}]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_generics.py
new/pydantic-1.10.4/tests/test_generics.py
--- old/pydantic-1.10.2/tests/test_generics.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/tests/test_generics.py 2022-12-30 10:53:51.000000000
+0100
@@ -7,6 +7,7 @@
ClassVar,
Dict,
Generic,
+ Iterable,
List,
Mapping,
Optional,
@@ -234,6 +235,32 @@
assert len(_generic_types_cache) == cache_size + 2
+def test_cache_keys_are_hashable():
+ cache_size = len(_generic_types_cache)
+ T = TypeVar('T')
+ C = Callable[[str, Dict[str, Any]], Iterable[str]]
+
+ class MyGenericModel(GenericModel, Generic[T]):
+ t: T
+
+ # Callable's first params get converted to a list, which is not hashable.
+ # Make sure we can handle that special case
+ Simple = MyGenericModel[Callable[[int], str]]
+ assert len(_generic_types_cache) == cache_size + 2
+ # Nested Callables
+ MyGenericModel[Callable[[C], Iterable[str]]]
+ assert len(_generic_types_cache) == cache_size + 4
+ MyGenericModel[Callable[[Simple], Iterable[int]]]
+ assert len(_generic_types_cache) == cache_size + 6
+ MyGenericModel[Callable[[MyGenericModel[C]], Iterable[int]]]
+ assert len(_generic_types_cache) == cache_size + 10
+
+ class Model(BaseModel):
+ x: MyGenericModel[Callable[[C], Iterable[str]]] = Field(...)
+
+ assert len(_generic_types_cache) == cache_size + 10
+
+
def test_generic_config():
data_type = TypeVar('data_type')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_networks.py
new/pydantic-1.10.4/tests/test_networks.py
--- old/pydantic-1.10.2/tests/test_networks.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/tests/test_networks.py 2022-12-30 10:53:51.000000000
+0100
@@ -36,6 +36,7 @@
'postgres://just-user@localhost:5432/app',
'postgresql+asyncpg://user:pass@localhost:5432/app',
'postgresql+pg8000://user:pass@localhost:5432/app',
+ 'postgresql+psycopg://postgres:postgres@localhost:5432/hatch',
'postgresql+psycopg2://postgres:postgres@localhost:5432/hatch',
'postgresql+psycopg2cffi://user:pass@localhost:5432/app',
'postgresql+py-postgresql://user:pass@localhost:5432/app',
@@ -262,9 +263,9 @@
def test_fragment_without_query():
- url =
validate_url('https://pydantic-docs.helpmanual.io/usage/types/#constrained-types')
+ url =
validate_url('https://docs.pydantic.dev/usage/types/#constrained-types')
assert url.scheme == 'https'
- assert url.host == 'pydantic-docs.helpmanual.io'
+ assert url.host == 'docs.pydantic.dev'
assert url.path == '/usage/types/'
assert url.query is None
assert url.fragment == 'constrained-types'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_parse.py
new/pydantic-1.10.4/tests/test_parse.py
--- old/pydantic-1.10.2/tests/test_parse.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/tests/test_parse.py 2022-12-30 10:53:51.000000000
+0100
@@ -46,6 +46,7 @@
m = MyModel.parse_obj('a')
assert m.dict() == {'__root__': 'a'}
assert m.__root__ == 'a'
+ assert MyModel.parse_obj(m) == m
def test_parse_root_list():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_schema.py
new/pydantic-1.10.4/tests/test_schema.py
--- old/pydantic-1.10.2/tests/test_schema.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/tests/test_schema.py 2022-12-30 10:53:51.000000000
+0100
@@ -459,6 +459,34 @@
}
+def test_enum_schema_cleandoc():
+ class FooBar(str, Enum):
+ """
+ This is docstring which needs to be cleaned up
+ """
+
+ foo = 'foo'
+ bar = 'bar'
+
+ class Model(BaseModel):
+ enum: FooBar
+
+ assert Model.schema() == {
+ 'title': 'Model',
+ 'type': 'object',
+ 'properties': {'enum': {'$ref': '#/definitions/FooBar'}},
+ 'required': ['enum'],
+ 'definitions': {
+ 'FooBar': {
+ 'title': 'FooBar',
+ 'description': 'This is docstring which needs to be cleaned
up',
+ 'enum': ['foo', 'bar'],
+ 'type': 'string',
+ }
+ },
+ }
+
+
def test_json_schema():
class Model(BaseModel):
a = b'foobar'
@@ -1495,6 +1523,38 @@
}
+def test_model_default():
+ """Make sure inner model types are encoded properly"""
+
+ class Inner(BaseModel):
+ a: Dict[Path, str] = {Path(): ''}
+
+ class Outer(BaseModel):
+ inner: Inner = Inner()
+
+ assert Outer.schema() == {
+ 'definitions': {
+ 'Inner': {
+ 'properties': {
+ 'a': {
+ 'additionalProperties': {'type': 'string'},
+ 'default': {'.': ''},
+ 'title': 'A',
+ 'type': 'object',
+ }
+ },
+ 'title': 'Inner',
+ 'type': 'object',
+ }
+ },
+ 'properties': {
+ 'inner': {'allOf': [{'$ref': '#/definitions/Inner'}], 'default':
{'a': {'.': ''}}, 'title': 'Inner'}
+ },
+ 'title': 'Outer',
+ 'type': 'object',
+ }
+
+
@pytest.mark.parametrize(
'kwargs,type_,expected_extra',
[
@@ -1654,7 +1714,13 @@
'title': 'Foo',
'type': 'object',
'properties': {
- 'a': {'type': 'object', 'title': 'A', 'default': {},
'patternProperties': {regex_str: {'type': 'string'}}}
+ 'a': {
+ 'type': 'object',
+ 'title': 'A',
+ 'default': {},
+ 'additionalProperties': {'type': 'string'},
+ 'patternProperties': {regex_str: {'type': 'string'}},
+ }
},
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_types.py
new/pydantic-1.10.4/tests/test_types.py
--- old/pydantic-1.10.2/tests/test_types.py 2022-09-05 18:35:13.000000000
+0200
+++ new/pydantic-1.10.4/tests/test_types.py 2022-12-30 10:53:51.000000000
+0100
@@ -1759,6 +1759,45 @@
Model(u='1234567')
+def test_strict_str_regex():
+ class Model(BaseModel):
+ u: StrictStr = Field(..., regex=r'^[0-9]+$')
+
+ assert Model(u='123').u == '123'
+
+ with pytest.raises(ValidationError, match='str type expected'):
+ Model(u=123)
+
+ with pytest.raises(ValidationError) as exc_info:
+ Model(u='abc')
+ assert exc_info.value.errors() == [
+ {
+ 'loc': ('u',),
+ 'msg': 'string does not match regex "^[0-9]+$"',
+ 'type': 'value_error.str.regex',
+ 'ctx': {'pattern': '^[0-9]+$'},
+ }
+ ]
+
+
+def test_string_regex():
+ class Model(BaseModel):
+ u: str = Field(..., regex=r'^[0-9]+$')
+
+ assert Model(u='123').u == '123'
+
+ with pytest.raises(ValidationError) as exc_info:
+ Model(u='abc')
+ assert exc_info.value.errors() == [
+ {
+ 'loc': ('u',),
+ 'msg': 'string does not match regex "^[0-9]+$"',
+ 'type': 'value_error.str.regex',
+ 'ctx': {'pattern': '^[0-9]+$'},
+ }
+ ]
+
+
def test_strict_bool():
class Model(BaseModel):
v: StrictBool
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic-1.10.2/tests/test_validators.py
new/pydantic-1.10.4/tests/test_validators.py
--- old/pydantic-1.10.2/tests/test_validators.py 2022-09-05
18:35:13.000000000 +0200
+++ new/pydantic-1.10.4/tests/test_validators.py 2022-12-30
10:53:51.000000000 +0100
@@ -7,7 +7,7 @@
import pytest
from typing_extensions import Literal
-from pydantic import BaseModel, ConfigError, Extra, Field, ValidationError,
errors, validator
+from pydantic import BaseModel, ConfigError, Extra, Field, ValidationError,
conlist, errors, validator
from pydantic.class_validators import make_generic_validator, root_validator
@@ -1329,3 +1329,19 @@
B(x='pika')
assert validate_stub.call_args_list == [mocker.call('B', 'pre'),
mocker.call('B', 'post')]
+
+
+def test_list_unique_items_with_optional():
+ class Model(BaseModel):
+ foo: Optional[List[str]] = Field(None, unique_items=True)
+ bar: conlist(str, unique_items=True) = Field(None)
+
+ assert Model().dict() == {'foo': None, 'bar': None}
+ assert Model(foo=None, bar=None).dict() == {'foo': None, 'bar': None}
+ assert Model(foo=['k1'], bar=['k1']).dict() == {'foo': ['k1'], 'bar':
['k1']}
+ with pytest.raises(ValidationError) as exc_info:
+ Model(foo=['k1', 'k1'], bar=['k1', 'k1'])
+ assert exc_info.value.errors() == [
+ {'loc': ('foo',), 'msg': 'the list has duplicated items', 'type':
'value_error.list.unique_items'},
+ {'loc': ('bar',), 'msg': 'the list has duplicated items', 'type':
'value_error.list.unique_items'},
+ ]