Repository: samuelcolvin/pydantic
Pull request #3553 (2021-12-20 21:01:20)

build(deps): bump cython from 0.29.25 to 0.29.26
Bumps [cython](https://github.com/cython/cython) from 0.29.25 to 0.29.26.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/cython/cython/blob/master/CHANGES.rst">cython's changelog</a>.</em></p>
<blockquote>
<h1>0.29.26 (2021-12-16)</h1>
<h2>Bugs fixed</h2>
<ul>
<li>
<p>An incompatibility with CPython 3.11.0a3 was resolved.
(Github issue :issue:<code>4499</code>)</p>
</li>
<li>
<p>The <code>in</code> operator failed on literal lists with starred expressions.
Patch by Arvind Natarajan.  (Github issue :issue:<code>3938</code>)</p>
</li>
<li>
<p>A C compiler warning in PyPy about a missing struct field initialisation was resolved.</p>
</li>
</ul>
<p>.. _0.29.25:</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/cython/cython/commit/3028e8c7ac296bc848d996e397c3354b3dbbd431"><code>3028e8c</code></a> Update changelog.</li>
<li><a href="https://github.com/cython/cython/commit/914bee4fa1a28e1b87fe9a5485490fc40420211b"><code>914bee4</code></a> Add &quot;tp_pypy_flags&quot; field to PyTypeObject struct when compiling in PyPy 6.0+ ...</li>
<li><a href="https://github.com/cython/cython/commit/8daf640dbf18cb72a705630f7c0d6799bd0c8e6a"><code>8daf640</code></a> Prepare release of 0.29.26.</li>
<li><a href="https://github.com/cython/cython/commit/4ce2721e655b562a8d8ee0edaa37122a0bcb5de1"><code>4ce2721</code></a> Revert &quot;Add tp_inline_values_offset to slot_table (0.29.x) (<a href="https://github-redirect.dependabot.com/cython/cython/issues/4473">GH-4473</a>)&quot;</li>
<li><a href="https://github.com/cython/cython/commit/1faf51f0811ea49b25280957fb84ac731ac16320"><code>1faf51f</code></a> Prevent in-list optimisation when the list contains starred expresssions (GH-...</li>
<li><a href="https://github.com/cython/cython/commit/20b3d5b5bd1e641781d994bfcac59d39bac2b999"><code>20b3d5b</code></a> Clean up CFLAGS/LDFLAGS setup in wheel build.</li>
<li><a href="https://github.com/cython/cython/commit/fc3685075dc9750fb5c849c0da2d84fe50f6b566"><code>fc36850</code></a> Update release date, now that it took a little longer.</li>
<li><a href="https://github.com/cython/cython/commit/488e21a34259258210f0be92c58618e1ea8a928f"><code>488e21a</code></a> Also upload the musllinux wheels to GH Releases.</li>
<li>See full diff in <a href="https://github.com/cython/cython/compare/0.29.25...0.29.26">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cython&package-manager=pip&previous-version=0.29.25&new-version=0.29.26)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/docs/examples/schema_ad_hoc.py b/docs/examples/schema_ad_hoc.py
index 6e93f913d..10862e162 100644
--- a/docs/examples/schema_ad_hoc.py
+++ b/docs/examples/schema_ad_hoc.py
@@ -2,7 +2,7 @@ from typing import Literal, Union
 
 from typing_extensions import Annotated
 
-from pydantic import BaseModel, Field, schema_json
+from pydantic import BaseModel, Field, schema_json_of
 
 
 class Cat(BaseModel):
@@ -17,4 +17,4 @@ class Dog(BaseModel):
 
 Pet = Annotated[Union[Cat, Dog], Field(discriminator='pet_type')]
 
-print(schema_json(Pet, title='The Pet Schema', indent=2))
+print(schema_json_of(Pet, title='The Pet Schema', indent=2))
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 2bc1b7dc1..88f06ea3f 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,12 +1,12 @@
 ansi2html==1.6.0
 flake8==4.0.1
 flake8-quotes==3.3.1
-hypothesis==6.31.4
+hypothesis==6.31.6
 markdown-include==0.6.0
 mdx-truly-sane-lists==1.2
 mkdocs==1.2.3
 mkdocs-exclude==1.0.2
-mkdocs-material==8.1.1
+mkdocs-material==8.1.3
 sqlalchemy
 orjson
 ujson
diff --git a/docs/usage/schema.md b/docs/usage/schema.md
index 9928b2782..458014a41 100644
--- a/docs/usage/schema.md
+++ b/docs/usage/schema.md
@@ -39,7 +39,7 @@ will be replaced with the model naming using `str.format()`.
 
 ## Getting schema of a specified type
 
-_Pydantic_ includes two standalone utility functions `schema` and `schema_json` that can be used to
+_Pydantic_ includes two standalone utility functions `schema_of` and `schema_json_of` that can be used to
 apply the schema generation logic used for _pydantic_ models in a more ad-hoc way.
 These functions behave similarly to `BaseModel.schema` and `BaseModel.schema_json`,
 but work with arbitrary pydantic-compatible types.
diff --git a/pydantic/__init__.py b/pydantic/__init__.py
index 0443acef6..982ea4755 100644
--- a/pydantic/__init__.py
+++ b/pydantic/__init__.py
@@ -67,8 +67,8 @@ __all__ = [
     'parse_file_as',
     'parse_obj_as',
     'parse_raw_as',
-    'schema',
-    'schema_json',
+    'schema_of',
+    'schema_json_of',
     # types
     'NoneStr',
     'NoneBytes',
diff --git a/pydantic/fields.py b/pydantic/fields.py
index ff7b962f7..44a3aa10b 100644
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -50,6 +50,7 @@ from .utils import (
     ValueItems,
     get_discriminator_alias_and_values,
     get_unique_discriminator_alias,
+    lenient_isinstance,
     lenient_issubclass,
     sequence_like,
     smart_deepcopy,
@@ -1048,7 +1049,7 @@ class ModelField(Representation):
                             return v, None
                     except TypeError:
                         # compound type
-                        if isinstance(v, get_origin(field.outer_type_)):
+                        if lenient_isinstance(v, get_origin(field.outer_type_)):
                             value, error = field.validate(v, values, loc=loc, cls=cls)
                             if not error:
                                 return value, None
diff --git a/pydantic/tools.py b/pydantic/tools.py
index f1d651cd4..9cdb4538e 100644
--- a/pydantic/tools.py
+++ b/pydantic/tools.py
@@ -7,7 +7,7 @@ from .parse import Protocol, load_file, load_str_bytes
 from .types import StrBytes
 from .typing import display_as_type
 
-__all__ = ('parse_file_as', 'parse_obj_as', 'parse_raw_as', 'schema', 'schema_json')
+__all__ = ('parse_file_as', 'parse_obj_as', 'parse_raw_as', 'schema_of', 'schema_json_of')
 
 NameFactory = Union[str, Callable[[Type[Any]], str]]
 
@@ -82,11 +82,11 @@ def parse_raw_as(
     return parse_obj_as(type_, obj, type_name=type_name)
 
 
-def schema(type_: Any, *, title: Optional[NameFactory] = None, **schema_kwargs: Any) -> 'DictStrAny':
+def schema_of(type_: Any, *, title: Optional[NameFactory] = None, **schema_kwargs: Any) -> 'DictStrAny':
     """Generate a JSON schema (as dict) for the passed model or dynamically generated one"""
     return _get_parsing_type(type_, type_name=title).schema(**schema_kwargs)
 
 
-def schema_json(type_: Any, *, title: Optional[NameFactory] = None, **schema_json_kwargs: Any) -> str:
+def schema_json_of(type_: Any, *, title: Optional[NameFactory] = None, **schema_json_kwargs: Any) -> str:
     """Generate a JSON schema (as JSON) for the passed model or dynamically generated one"""
     return _get_parsing_type(type_, type_name=title).schema_json(**schema_json_kwargs)
diff --git a/pydantic/utils.py b/pydantic/utils.py
index ec94f76c7..d4ca69395 100644
--- a/pydantic/utils.py
+++ b/pydantic/utils.py
@@ -53,6 +53,7 @@ __all__ = (
     'import_string',
     'sequence_like',
     'validate_field_name',
+    'lenient_isinstance',
     'lenient_issubclass',
     'in_ipython',
     'deep_update',
@@ -163,6 +164,13 @@ def validate_field_name(bases: List[Type['BaseModel']], field_name: str) -> None
             )
 
 
+def lenient_isinstance(o: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]]) -> bool:
+    try:
+        return isinstance(o, class_or_tuple)
+    except TypeError:
+        return False
+
+
 def lenient_issubclass(cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]]) -> bool:
     try:
         return isinstance(cls, type) and issubclass(cls, class_or_tuple)
diff --git a/requirements.txt b/requirements.txt
index 5a2b15ce9..95aef0852 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
 # requirements for compilation and from setup.py so dependabot prompts us to test with latest version of these packages
 
-Cython==0.29.25;sys_platform!='win32'
+Cython==0.29.26;sys_platform!='win32'
 devtools==0.8.0
 email-validator==1.1.3
 dataclasses==0.6; python_version < '3.7'


Test patch:
diff --git a/tests/requirements-linting.txt b/tests/requirements-linting.txt
index 81614a46e..40b92adc1 100644
--- a/tests/requirements-linting.txt
+++ b/tests/requirements-linting.txt
@@ -1,7 +1,7 @@
 black==21.12b0
 flake8==4.0.1
 flake8-quotes==3.3.1
-hypothesis==6.31.4
+hypothesis==6.31.6
 isort==5.10.1
 mypy==0.910
 pre-commit==2.16.0
diff --git a/tests/requirements-testing.txt b/tests/requirements-testing.txt
index faa291edf..2e4964458 100644
--- a/tests/requirements-testing.txt
+++ b/tests/requirements-testing.txt
@@ -1,5 +1,5 @@
 coverage==6.2
-hypothesis==6.31.4
+hypothesis==6.31.6
 # pin importlib-metadata as upper versions need typing-extensions to work if on python < 3.8
 importlib-metadata==3.1.0;python_version<"3.8"
 mypy==0.910
diff --git a/tests/test_tools.py b/tests/test_tools.py
index 97784d552..689b32d4c 100644
--- a/tests/test_tools.py
+++ b/tests/test_tools.py
@@ -5,7 +5,7 @@ import pytest
 
 from pydantic import BaseModel, ValidationError
 from pydantic.dataclasses import dataclass
-from pydantic.tools import parse_file_as, parse_obj_as, parse_raw_as, schema, schema_json
+from pydantic.tools import parse_file_as, parse_obj_as, parse_raw_as, schema_json_of, schema_of
 
 
 @pytest.mark.parametrize('obj,type_,parsed', [('1', int, 1), (['1'], List[int], [1])])
@@ -101,11 +101,11 @@ def test_raw_as():
 
 
 def test_schema():
-    assert schema(Union[int, str], title='IntOrStr') == {
+    assert schema_of(Union[int, str], title='IntOrStr') == {
         'title': 'IntOrStr',
         'anyOf': [{'type': 'integer'}, {'type': 'string'}],
     }
-    assert schema_json(Union[int, str], title='IntOrStr', indent=2) == (
+    assert schema_json_of(Union[int, str], title='IntOrStr', indent=2) == (
         '{\n'
         '  "title": "IntOrStr",\n'
         '  "anyOf": [\n'
diff --git a/tests/test_types.py b/tests/test_types.py
index 2a3161316..bbf4c23b1 100644
--- a/tests/test_types.py
+++ b/tests/test_types.py
@@ -27,7 +27,7 @@ from typing import (
 from uuid import UUID
 
 import pytest
-from typing_extensions import Literal
+from typing_extensions import Literal, TypedDict
 
 from pydantic import (
     UUID1,
@@ -3120,6 +3120,22 @@ def test_smart_union_compouned_types_edge_case():
     assert Model(x=[1, '2']).x == ['1', '2']
 
 
+def test_smart_union_typeddict():
+    class Dict1(TypedDict):
+        foo: str
+
+    class Dict2(TypedDict):
+        bar: str
+
+    class M(BaseModel):
+        d: Union[Dict2, Dict1]
+
+        class Config:
+            smart_union = True
+
+    assert M(d=dict(foo='baz')).d == {'foo': 'baz'}
+
+
 @pytest.mark.parametrize(
     'value,result',
     (