profile
viewpoint
Samuel Colvin samuelcolvin @MyHealthChecked London, United Kingdom http://scolvin.com Software developer and CTO @myhealthchecked. Python, TypeScript, rust.

rq/rq 8030

Simple job queues for Python

samuelcolvin/arq 1020

Fast job queuing and RPC in python with asyncio and redis.

aio-libs/aiohttp-devtools 217

dev tools for aiohttp

samuelcolvin/aioaws 75

Asyncio compatible SDK for aws services.

samuelcolvin/aiohttp-vs-sanic-vs-japronto 53

Rough benchmarks of of aiohttp and sanic

samuelcolvin/buildpg 48

Query building for the postgresql prepared statements and asyncpg.

samuelcolvin/Bokeh.jl 45

Bokeh Bindings for Julia

samuelcolvin/aiohttp-toolbox 23

Tools for aiohttp

Pull request review commentsamuelcolvin/pydantic

feat: Add unique items validation to constrained lists

 def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':          return v +    @classmethod+    def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':+        try:+            if v and len(set(v)) != len(v):+                raise errors.ListUniqueItemsError(not_unique=len(v) - len(set(v)))+        except TypeError:+            # failover for unhashable types+            unique = list() -def conlist(item_type: Type[T], *, min_items: int = None, max_items: int = None) -> Type[List[T]]:+            if v and len([unique.append(i) for i in v if i not in unique]) != len(v):  # type: ignore

modifying unique inside a comprehension is somewhat unorthodox, also (if we don't care about how many items are not unique, which I will mostly be the case) we can do this faster by raising the error as soon as we find a duplicate.

Something like

for i, value in enumerate(v, start=1):
    if value in v[i:]:
        raise errors.ListUniqueItemsError()

I haven't done any profiling but I feel something like this should be quicker.

nuno-andre

comment created time in 17 hours

PullRequestReviewEvent

Pull request review commentsamuelcolvin/pydantic

feat: Add unique items validation to constrained lists

 def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':          return v +    @classmethod+    def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':+        try:

I'm not sure about this "try with a set, then fallback approach", I think it might be cleaner to always use the approach below.

nuno-andre

comment created time in 17 hours

Pull request review commentsamuelcolvin/pydantic

feat: Add unique items validation to constrained lists

 def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':          return v +    @classmethod+    def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]':+        try:

alternatively, we could give the user a choice of either they want to use a set or not.

nuno-andre

comment created time in 17 hours

PullRequestReviewEvent

pull request commentsamuelcolvin/pydantic

Try to evaluate forward refs after model created

this is great, thank you so much.

uriyyo

comment created time in 17 hours

push eventsamuelcolvin/pydantic

Yurii Karabas

commit sha 415eb54f966f0eec7cb2fd0aa61492c17e606367

Try to evaluate forward refs after model created (#2588) * Try to evaluate forward refs after model created * Upadate docs and remove code duplication * Update changes/2588-uriyyo.md Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * Update docs/usage/postponed_annotations.md Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * Remove unused import Co-authored-by: Eric Jolibois <em.jolibois@gmail.com>

view details

push time in 17 hours

PR merged samuelcolvin/pydantic

Reviewers
Try to evaluate forward refs after model created ready for review

<!-- Thank you for your contribution! --> <!-- Unless your change is trivial, please create an issue to discuss the change before creating a PR --> <!-- See https://pydantic-docs.helpmanual.io/contributing/ for help on Contributing -->

Change Summary

Try to evaluate forward refs after model created. <!-- Please give a short summary of the changes. -->

So it will not be required to use update_forward_refs in the case of self-referencing model:

from __future__ import annotations

from pydantic import BaseModel
from typing import Optional


class Foo(BaseModel):
    foo: Optional[Foo]


assert Foo.__fields__['foo'].type_ is Foo

<!-- Are there any issues opened that will be resolved by merging this change? -->

Checklist

  • [x] Unit tests for the changes exist
  • [x] Tests pass on CI and coverage remains at 100%
  • [x] Documentation reflects the changes where applicable
  • [x] changes/<pull request or issue id>-<github username>.md file added describing change (see changes/README.md for details)
+91 -21

3 comments

7 changed files

uriyyo

pr closed time in 17 hours

pull request commentsamuelcolvin/pydantic

refactor: change pydantic dataclass decorator

Please update.

Also, I'm a big confused about where we are with mypy compatibility. Does this make things better or worse, or not really make a difference.

If it makes things worse in any way, we should probably make that clear.

PrettyWood

comment created time in 17 hours

Pull request review commentsamuelcolvin/pydantic

refactor: change pydantic dataclass decorator

 def __get_validators__(cls: Type['Dataclass']) -> 'CallableGenerator':         def __validate__(cls: Type['DataclassT'], v: Any) -> 'DataclassT':             pass -        def __call__(self: 'DataclassT', *args: Any, **kwargs: Any) -> 'DataclassT':-            pass +__all__ = [+    'dataclass',+    'set_validation',+    'create_pydantic_model_from_dataclass',+    'is_builtin_dataclass',+    'make_dataclass_validator',+] -def _validate_dataclass(cls: Type['DataclassT'], v: Any) -> 'DataclassT':-    if isinstance(v, cls):-        return v-    elif isinstance(v, (list, tuple)):-        return cls(*v)-    elif isinstance(v, dict):-        return cls(**v)-    # In nested dataclasses, v can be of type `dataclasses.dataclass`.-    # But to validate fields `cls` will be in fact a `pydantic.dataclasses.dataclass`,-    # which inherits directly from the class of `v`.-    elif is_builtin_dataclass(v) and cls.__bases__[0] is type(v):++@overload+def dataclass(+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> Callable[[Type[Any]], 'DataclassClassOrWrapper']:+    ...+++@overload+def dataclass(+    _cls: Type[Any],+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> 'DataclassClassOrWrapper':+    ...+++def dataclass(+    _cls: Optional[Type[Any]] = None,+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> Union[Callable[[Type[Any]], 'DataclassClassOrWrapper'], 'DataclassClassOrWrapper']:+    """+    Like the python standard lib dataclasses but with type validation.+    The result is either pydantic dataclass that will validate input data
    The result is either a pydantic dataclass that will validate input data
PrettyWood

comment created time in 18 hours

Pull request review commentsamuelcolvin/pydantic

refactor: change pydantic dataclass decorator

 def __get_validators__(cls: Type['Dataclass']) -> 'CallableGenerator':         def __validate__(cls: Type['DataclassT'], v: Any) -> 'DataclassT':             pass -        def __call__(self: 'DataclassT', *args: Any, **kwargs: Any) -> 'DataclassT':-            pass +__all__ = [+    'dataclass',+    'set_validation',+    'create_pydantic_model_from_dataclass',+    'is_builtin_dataclass',+    'make_dataclass_validator',+] -def _validate_dataclass(cls: Type['DataclassT'], v: Any) -> 'DataclassT':-    if isinstance(v, cls):-        return v-    elif isinstance(v, (list, tuple)):-        return cls(*v)-    elif isinstance(v, dict):-        return cls(**v)-    # In nested dataclasses, v can be of type `dataclasses.dataclass`.-    # But to validate fields `cls` will be in fact a `pydantic.dataclasses.dataclass`,-    # which inherits directly from the class of `v`.-    elif is_builtin_dataclass(v) and cls.__bases__[0] is type(v):++@overload+def dataclass(+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> Callable[[Type[Any]], 'DataclassClassOrWrapper']:+    ...+++@overload+def dataclass(+    _cls: Type[Any],+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> 'DataclassClassOrWrapper':+    ...+++def dataclass(+    _cls: Optional[Type[Any]] = None,+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> Union[Callable[[Type[Any]], 'DataclassClassOrWrapper'], 'DataclassClassOrWrapper']:+    """+    Like the python standard lib dataclasses but with type validation.+    The result is either pydantic dataclass that will validate input data+    or a wrapper that will trigger validation around a stdlib dataclass+    to avoid modifying it directly+    """+    the_config = get_config(config)++    def wrap(cls: Type[Any]) -> 'DataclassClassOrWrapper':         import dataclasses -        return cls(**dataclasses.asdict(v))-    else:-        raise DataclassTypeError(class_name=cls.__name__)+        if is_builtin_dataclass(cls):+            should_validate_on_init = False if validate_on_init is None else validate_on_init+            _add_pydantic_validation_attributes(cls, the_config, should_validate_on_init, '')+            return DataclassProxy(cls) +        else:+            dc_cls_doc = cls.__doc__ or ''  # needs to be done before generating dataclass+            dc_cls = dataclasses.dataclass(  # type: ignore+                cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen+            )+            should_validate_on_init = True if validate_on_init is None else validate_on_init+            _add_pydantic_validation_attributes(dc_cls, the_config, should_validate_on_init, dc_cls_doc)+            return dc_cls -def _get_validators(cls: Type['Dataclass']) -> 'CallableGenerator':-    yield cls.__validate__+    if _cls is None:+        return wrap +    return wrap(_cls) -def setattr_validate_assignment(self: 'Dataclass', name: str, value: Any) -> None:-    if self.__initialised__:-        d = dict(self.__dict__)-        d.pop(name, None)-        known_field = self.__pydantic_model__.__fields__.get(name, None)-        if known_field:-            value, error_ = known_field.validate(value, d, loc=name, cls=self.__class__)-            if error_:-                raise ValidationError([error_], self.__class__) -    object.__setattr__(self, name, value)+@contextmanager+def set_validation(cls: Type['DataclassT'], value: bool) -> Generator[Type['DataclassT'], None, None]:+    original_run_validation = cls.__pydantic_run_validation__+    try:+        cls.__pydantic_run_validation__ = value+        yield cls+    finally:+        cls.__pydantic_run_validation__ = original_run_validation  -def is_builtin_dataclass(_cls: Type[Any]) -> bool:+class DataclassProxy:+    __slots__ = '__dataclass__'++    def __init__(self, dc_cls: Type['Dataclass']) -> None:+        object.__setattr__(self, '__dataclass__', dc_cls)++    def __call__(self, *args: Any, **kwargs: Any) -> Any:

mypy doesn't recognising a pydantic dataclass as dataclass with this, but from my tests it doesn't on master/v1.8 either.

It would be great if there was a way to get this to work out of the box. But since it's not a regression, it shouldn't block this PR.

PrettyWood

comment created time in 17 hours

Pull request review commentsamuelcolvin/pydantic

refactor: change pydantic dataclass decorator

 def __call__(self, schema: Dict[str, Any], model_class: Type[BaseModel]) -> None else:     SchemaExtraCallable = Callable[..., None] -__all__ = 'BaseConfig', 'Extra', 'inherit_config', 'prepare_config'+__all__ = 'BaseConfig', 'ConfigDict', 'get_config', 'Extra', 'compiled', 'inherit_config', 'prepare_config'++try:+    import cython  # type: ignore+except ImportError:+    compiled: bool = False

humm, isn't this a breaking change as some people maybe have from pydantic.main import compiled?

If we think it's okay to move this, I would say version.py is a better play to put this?

PrettyWood

comment created time in 18 hours

Pull request review commentsamuelcolvin/pydantic

refactor: change pydantic dataclass decorator

 def __get_validators__(cls: Type['Dataclass']) -> 'CallableGenerator':         def __validate__(cls: Type['DataclassT'], v: Any) -> 'DataclassT':             pass -        def __call__(self: 'DataclassT', *args: Any, **kwargs: Any) -> 'DataclassT':-            pass +__all__ = [+    'dataclass',+    'set_validation',+    'create_pydantic_model_from_dataclass',+    'is_builtin_dataclass',+    'make_dataclass_validator',+] -def _validate_dataclass(cls: Type['DataclassT'], v: Any) -> 'DataclassT':-    if isinstance(v, cls):-        return v-    elif isinstance(v, (list, tuple)):-        return cls(*v)-    elif isinstance(v, dict):-        return cls(**v)-    # In nested dataclasses, v can be of type `dataclasses.dataclass`.-    # But to validate fields `cls` will be in fact a `pydantic.dataclasses.dataclass`,-    # which inherits directly from the class of `v`.-    elif is_builtin_dataclass(v) and cls.__bases__[0] is type(v):++@overload+def dataclass(+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> Callable[[Type[Any]], 'DataclassClassOrWrapper']:+    ...+++@overload+def dataclass(+    _cls: Type[Any],+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> 'DataclassClassOrWrapper':+    ...+++def dataclass(+    _cls: Optional[Type[Any]] = None,+    *,+    init: bool = True,+    repr: bool = True,+    eq: bool = True,+    order: bool = False,+    unsafe_hash: bool = False,+    frozen: bool = False,+    config: Union[ConfigDict, Type[Any], None] = None,+    validate_on_init: Optional[bool] = None,+) -> Union[Callable[[Type[Any]], 'DataclassClassOrWrapper'], 'DataclassClassOrWrapper']:+    """+    Like the python standard lib dataclasses but with type validation.+    The result is either pydantic dataclass that will validate input data+    or a wrapper that will trigger validation around a stdlib dataclass+    to avoid modifying it directly+    """+    the_config = get_config(config)++    def wrap(cls: Type[Any]) -> 'DataclassClassOrWrapper':         import dataclasses -        return cls(**dataclasses.asdict(v))-    else:-        raise DataclassTypeError(class_name=cls.__name__)+        if is_builtin_dataclass(cls):+            should_validate_on_init = False if validate_on_init is None else validate_on_init+            _add_pydantic_validation_attributes(cls, the_config, should_validate_on_init, '')+            return DataclassProxy(cls) +        else:+            dc_cls_doc = cls.__doc__ or ''  # needs to be done before generating dataclass+            dc_cls = dataclasses.dataclass(  # type: ignore+                cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen+            )+            should_validate_on_init = True if validate_on_init is None else validate_on_init+            _add_pydantic_validation_attributes(dc_cls, the_config, should_validate_on_init, dc_cls_doc)+            return dc_cls -def _get_validators(cls: Type['Dataclass']) -> 'CallableGenerator':-    yield cls.__validate__+    if _cls is None:+        return wrap +    return wrap(_cls) -def setattr_validate_assignment(self: 'Dataclass', name: str, value: Any) -> None:-    if self.__initialised__:-        d = dict(self.__dict__)-        d.pop(name, None)-        known_field = self.__pydantic_model__.__fields__.get(name, None)-        if known_field:-            value, error_ = known_field.validate(value, d, loc=name, cls=self.__class__)-            if error_:-                raise ValidationError([error_], self.__class__) -    object.__setattr__(self, name, value)+@contextmanager+def set_validation(cls: Type['DataclassT'], value: bool) -> Generator[Type['DataclassT'], None, None]:+    original_run_validation = cls.__pydantic_run_validation__+    try:+        cls.__pydantic_run_validation__ = value+        yield cls+    finally:+        cls.__pydantic_run_validation__ = original_run_validation  -def is_builtin_dataclass(_cls: Type[Any]) -> bool:+class DataclassProxy:+    __slots__ = '__dataclass__'++    def __init__(self, dc_cls: Type['Dataclass']) -> None:+        object.__setattr__(self, '__dataclass__', dc_cls)++    def __call__(self, *args: Any, **kwargs: Any) -> Any:+        with set_validation(self.__dataclass__, True):+            return self.__dataclass__(*args, **kwargs)++    def __getattr__(self, name: str) -> Any:+        return getattr(self.__dataclass__, name)+

    def __instancecheck__(self, instance):
        return isinstance(instance, self.__dataclass__)

Should fix the assert not isinstance(validated_a, A_PY) case in the above comment.

PrettyWood

comment created time in 17 hours

PullRequestReviewEvent

Pull request review commentsamuelcolvin/pydantic

refactor: change pydantic dataclass decorator

 class BaseConfig:     json_encoders: Dict[Type[Any], AnyCallable] = {}     underscore_attrs_are_private: bool = False -    # Whether or not inherited models as fields should be reconstructed as base model+    # whether or not inherited models as fields should be reconstructed as base model     copy_on_model_validation: bool = True+    # whether dataclass `__post_init__` should be run after validation+    post_init_after_validation: bool = False

I think this could be more clearly named/described, perhaps something like

    post_init_call: Literal['before_validation', 'after_validation'] = 'before_validation'

?

PrettyWood

comment created time in 18 hours

PullRequestReviewEvent

pull request commentsamuelcolvin/pydantic

Support discriminated union

something weird seems to be happening where tests aren't be started. Maybe it's just a matter of time?

PrettyWood

comment created time in 18 hours

push eventPrettyWood/pydantic

Samuel Colvin

commit sha 6d989763bdf0823430a3c1cca60983a345a09af6

bump to prompt tests

view details

push time in 18 hours

pull request commentsamuelcolvin/pydantic

Improve generic subclass support

great, thank you.

diabolo-dan

comment created time in 18 hours

push eventsamuelcolvin/pydantic

diabolo-dan

commit sha e71f53d2b5a3a04962ecdf50edd021d0666a332c

Improve generic subclass support (#2549) * Derive concrete subclasses for parameterised generics * Resolve type issues * Add negative assertions to generic subclass tests * Remove incorrect subclassing of partial. The type was incorrectly being picked up for this style of subclassing, and it can be regardless inferred through cls. * Apply feedback: * Improve parameterisation explanation * fix typos * Alias Parameterisation type * Apply suggestions from code review * start docstring with newline. * Use None as default over empty tuple. Co-authored-by: Samuel Colvin <samcolvin@gmail.com> * Combine _assigned_parameters cases in __paramaterized_bases__ of generics * Add description for the `_assigned_parameters` variable. Co-authored-by: Samuel Colvin <samcolvin@gmail.com> Co-authored-by: Samuel Colvin <s@muelcolvin.com>

view details

push time in 18 hours

issue closedsamuelcolvin/pydantic

GenericModel - Recursive abstract class fails validation

Checks

  • [x] I added a descriptive title to this issue
  • [x] I have searched (google, github) for similar issues and couldn't find anything
  • [x] I have read and followed the docs and still think this is a bug

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.6.1
            pydantic compiled: False
                 install path: /wayfair/home/ch438l/pydantic/pydantic
               python version: 3.6.8 (default, Aug 10 2019, 06:54:07)  [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
                     platform: Linux-3.10.0-862.3.2.el7.x86_64-x86_64-with-centos-7.5.1804-Core
     optional deps. installed: ['typing-extensions', 'email-validator', 'devtools']

If I try to define an attribute on a generic model to be a generic abstract class, then the model will fail to validate. Here's a failing test case:

@skip_36
def test_abstract_generic_type_recursion():
    T = TypeVar('T')

    class BaseInnerClass(GenericModel, abc.ABC, Generic[T]):
        base_data: T

        @abc.abstractmethod
        def base_abstract(self) -> None:
            pass

    class ConcreteInnerClass(BaseInnerClass[T], Generic[T]):

        def base_abstract(self) -> None:
            return None

    class OuterClass(GenericModel, Generic[T]):
        inner_class: BaseInnerClass[T]

    OuterClass[int](inner_class=ConcreteInnerClass[int](base_data=2))

It appears to be failing because the isinstance(value, cls) check is failing for the generic type.

closed time in 18 hours

choogeboom

PR merged samuelcolvin/pydantic

Reviewers
Improve generic subclass support ready for review

<!-- Thank you for your contribution! --> <!-- Unless your change is trivial, please create an issue to discuss the change before creating a PR --> <!-- See https://pydantic-docs.helpmanual.io/contributing/ for help on Contributing -->

Change Summary

<!-- Please give a short summary of the changes. --> Add parameterised subclasses to __bases__ when constructing new parameterised classes, so that A <: B => A[int] <: B[int].

This helps to facilitate a use case based on abstract classes, and leads to less unexpected behaviour when comparing between concrete versions of classes.

Related issue number

<!-- Are there any issues opened that will be resolved by merging this change? -->

fix #2007

Checklist

  • [x] Unit tests for the changes exist
  • [ ] Tests pass on CI and coverage remains at 100%
  • [ ] Documentation reflects the changes where applicable
  • [x] changes/<pull request or issue id>-<github username>.md file added describing change (see changes/README.md for details)
+169 -5

6 comments

4 changed files

diabolo-dan

pr closed time in 18 hours

push eventPrettyWood/pydantic

Samuel Colvin

commit sha 7fffa17917c695b959f98eb8bcb64b0af6649ee1

bump to fix fastapi tests

view details

push time in 18 hours

push eventdiabolo-dan/pydantic

Eric Jolibois

commit sha babbd4c59d1e87a433953319f5cde486020e85ca

fix: attrs + cattrs benchmark (#2863)

view details

Sebastián Ramírez

commit sha c7d5259c0df844654a95c479c7464c4c4716fcb9

🔥 Unpin SQLAlchemy version for FastAPI tests (#2865) as it is now pinned in FastAPI, and soon I will upgrade its version

view details

Eric Jolibois

commit sha 2549c3012dbc9249a17257a7fbd0d130ab2fc957

build(deps-dev): bump dependencies (#2867) black: 21.4b0 -> 21.5b2 flake8: 3.9.1 -> 3.9.2 hypothesis: 6.10.1 -> 6.13.10 mkdocs-material: 7.1.4 -> 7.1.6 pytest: 6.2.3 -> 6.2.4 pytest-cov: 2.11.1 -> 2.12.0 typing-extensions: 3.7.4.3 -> 3.10.0.0

view details

Rémi Benoit

commit sha 920d71b7089974dc78706c93946040e40e8f9c19

Fix mypy plugin link in doc (#2747)

view details

Eric Jolibois

commit sha c489445cea40c4962ecfa9e342eb30a0ba819129

fix: mypy plugin link in docs (#2869)

view details

Ratul Maharaj

commit sha aca18a9863464c7a52e29faade0edb9df00291d6

Added Talk Python Episode 313 to docs (#2712) * Added Talk Python Episode 313 * Added changes file * Update docs/index.md Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * Fixed typo in Michael's name Co-authored-by: Eric Jolibois <em.jolibois@gmail.com>

view details

Peter Roelants

commit sha 2e2edf4f112478ffa3398452a9f862ed91daacbb

Allow custom CFLAGS and update documentation on reducing size. (#2517) Squashed commit Co-authored-by: Eric Jolibois <em.jolibois@gmail.com>

view details

Marcelo Trylesinski

commit sha a4cb4ee3bc57911a18b13643c44ab14e2ea28d33

feat: add PastDate and FutureDate types (#2425) * feat: add PastDate and FutureDate types * add changes file * add tests * fix: json schema * fix: black format * less code duplicated * add dates on success.py * fix past and future dates * ♻️ Apply Samuel's comments * 🚨 Satisfy flake8 * 🔥 Remove _DateValueError * test: add last explicit case Co-authored-by: PrettyWood <em.jolibois@gmail.com>

view details

Eric Jolibois

commit sha 4a54f393ad20ee91b51cd7a49ec46771ba4f8a18

Add python 3.10 support (#2885) * refactor: extra `BaseConfig` and `Extra` in dedicated `config` module * refactor: clean useless `#noqa: F401` * refactor: clean useless `#noqa: F811` * refactor: replace enum check Error with 3.10 > DeprecationWarning: accessing one member from another is not supported * refactor: avoid using `distutils` directly error with python 3.10 > DeprecationWarning: The distutils package is deprecated and slated > for removal in Python 3.12. > Use setuptools or check PEP 632 for potential alternatives * fix: `__annotations__` always exists * fix: origin of `typing.Hashable` is not `None` * ci: add run with 3.10.0b2 * docs: add 3.10 * feat: support `|` union operator properly `|` operator has origin `types.Union` (and not `typing.Union`) * fix: enum repr is different with 3.10+ * fix: error message changed a bit change from basic `__init__` to `test_hashable_required.<locals>.MyDataclass.__init__()` (with `__qualname__`) * fix: always exists and is not inherited anymore * fix: avoid calling `asyncio.get_event_loop` directly With python 3.10, calling it results in > DeprecationWarning: There is no current event loop * fix(ci): do not run 3.10 on linux for now For now it can not be compiled. Let's just skip the check on linux for now instead of tuning the CI pipeline * fix(ci): ignore DeprecationWarning raised by `mypy` on windows * docs: add change file

view details

Eric Jolibois

commit sha 945bc1161f286c447496fa9988661ee7b1f0e18a

fix(ci): ignore pytest warning for fastapi tests (#2999)

view details

Eric Jolibois

commit sha 0c26c1c4e288e0d41d2c3890d5b3befa7579455c

chore(ci): update python 3.10 version (#3000) * chore(ci): update python 3.10 version * Revert "fix: enum repr is different with 3.10+" This reverts commit b1c8d9ef1396959ff9d88bb2ed16d99dd3146151.

view details

Eric Jolibois

commit sha 5ccbdcb5904f35834300b01432a665c75dc02296

chore(ci): remove warning filter for fastapi tests (#3001) Now that https://github.com/tiangolo/fastapi/pull/2790 has been merged in master, we don't need to filter those warnings anymore

view details

Eric Jolibois

commit sha 21d002ec6e5ac4d38eed88b1ec1808f5c44b24e6

chore(ci): update to python 3.10.0-rc.1 (#3085) * refactor: rename `is_union` into `is_union_origin` * fix: "new" union and generic types are not the same as `typing.GenericAlias` * chore: rename param * fix(ci): name changed for 3.10 * fix: mypy

view details

Eric Jolibois

commit sha 796a7531cda0ca54ee0294074b098ac444408aeb

chore(deps): bump requirements (#3166) * chore(deps): bump requirements * chore(deps-dev): bump lint requirements * chore(deps-dev): add test requirements * chore(deps-dev): last bumps * fix: mypy update * chore: docs bumps

view details

Christian Clauss

commit sha 90080ba0de12e561b138ce221b5a67dcd932ab3e

Fix typos discovered by codespell (#3096)

view details

Davis Kirkendall

commit sha 3d287594e086c109d8277fcb2504974d61eb4361

Allow collections.abc.Callable to be used as type in python 3.9 (#2519) * Allow collections.abc.Callable to be used as type in python 3.9 * Add is_none_type as function to check none types by identity * Modify `typing.is_none_type` to work in python 3.6 and 3.7 * Add tests for none types in typing.py * Apply review comments on #2519 * Add different implementations depending on python version * Add tests for is_none_type * Add change entry * Fix field info repr * Remove unneeded try/except for python < 3.8 * Add comment explaining alternative is_none_type implementation * fix: typo Co-authored-by: PrettyWood <em.jolibois@gmail.com>

view details

Nuno André

commit sha 5549e8d37980f0c4b23e76c3e4cbdee147d30818

Fix recursive ORM parsing error (#2718) The _ORM mode_ doesn't parse dictionaries if it's not explicitly called.

view details

Fernando ike

commit sha 1a9f59dc1e11e6d0022636b53f7f7784a84f8c84

Support postgresql+asyncpg schema for PostgresDsn (#2567) * Added suport to postgresql async driver * Added postgres+asyncpg in the doc. * Added changes file * Added postgresql+pg8000 schema * ran make format * Update docs/usage/types.md Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com> * Changed from schema to scheme Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * fixed typo scheme * fixed merge schema * changed to one line description Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * added others DBAPI dialects. * Added two # by PrettyWood Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * fix typo by PrettyWood Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * Fixed typo by PrettyWood Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> * added postgresql+psycopg2 in changes dir * Fixed typo by @samuelcolvin Co-authored-by: Samuel Colvin <samcolvin@gmail.com> * docs: fix typo * chore: sort alphabetically Co-authored-by: Fernando Ike <fernando.ike@maburix.com> Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com> Co-authored-by: Eric Jolibois <em.jolibois@gmail.com> Co-authored-by: Samuel Colvin <samcolvin@gmail.com>

view details

Mikhail Sitnikov

commit sha 65fc336cf3f15310a7438de2163841470ad6204e

added `KafkaDsn` to `networks.py` and add default ports for `HttpUrl` (#2447) * added KafkaDsn to network * added short description to chandes folder * added default non-displayable ports to HttpUrl model * added info to changes folder * fix: support non default ports in HttpUrl * fix pr issues * remove noqa * add more typing by @PrettyWood * add default http and https ports to `HttpUrl` model * fix mypy * chore: do not add implementation details Co-authored-by: PrettyWood <em.jolibois@gmail.com>

view details

Vasilis Gerakaris

commit sha 8417b3bb5c46fef1b53ca1030ce92dc82b5cdfd7

add `FileUrl` type for `file://` schemes, add `host_required` parameter (#2434) * add `FileUrl` type for `file://` schemes Also add a `host_required` parameter, True by default, False in `FileUrl` and `RedisDsn`. * chore: useless extra in assert statement Co-authored-by: PrettyWood <em.jolibois@gmail.com>

view details

push time in 18 hours

push eventsamuelcolvin/pydantic

Eric Jolibois

commit sha a35cde90af9caaa4d1670508255a38b6e361228a

feat(schema): set `minItems` and `maxItems` in JSON schema for tuples (#2497) * feat(schema): enforce length in generated JSON schema for tuple type * docs: add change file * docs: update documentation * simplify a bit * always set array

view details

push time in 18 hours

PR merged samuelcolvin/pydantic

feat(schema): set `minItems` and `maxItems` in JSON schema for tuples ready for review

<!-- Thank you for your contribution! --> <!-- Unless your change is trivial, please create an issue to discuss the change before creating a PR --> <!-- See https://pydantic-docs.helpmanual.io/contributing/ for help on Contributing -->

Change Summary

We didn't enforce the length of the tuple in the JSON schema. We could hence set smaller or longer tuples. Also handles case of empty tuple by not setting items at all to fix #2496

<!-- Please give a short summary of the changes. -->

Related issue number

<!-- Are there any issues opened that will be resolved by merging this change? -->

Checklist

  • [x] Unit tests for the changes exist
  • [x] Tests pass on CI and coverage remains at 100%
  • [x] Documentation reflects the changes where applicable
  • [x] changes/<pull request or issue id>-<github username>.md file added describing change (see changes/README.md for details)
+66 -26

4 comments

5 changed files

PrettyWood

pr closed time in 18 hours

issue closedsamuelcolvin/pydantic

Empty tuple type does not generate valid JSON schema

Checks

  • [x] I added a descriptive title to this issue
  • [x] I have searched (google, github) for similar issues and couldn't find anything
  • [x] I have read and followed the docs and still think this is a bug

<!-- Sorry to sound so draconian, but every second saved replying to issues is time spend improving pydantic :-) -->

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

 python -c "import pydantic.utils; print(pydantic.utils.version_info())"
             pydantic version: 1.8.1
            pydantic compiled: True
                 install path: /Users/smacpher/.virtualenvs/nucleus/lib/python3.6/site-packages/pydantic
               python version: 3.6.9 (default, Oct 16 2019, 11:14:39)  [GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.10.44.4)]
                     platform: Darwin-17.7.0-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions']

<!-- or if you're using pydantic prior to v1.3, manually include: OS, python version and pydantic version -->

<!-- Please read the docs and search through issues to confirm your bug hasn't already been reported. -->

<!-- Where possible please include a self-contained code snippet describing your bug: -->

import jsonschema
import pydantic

from typing import Tuple

class Model(pydantic.BaseModel):
    f: Tuple[()]

jsonschema.Draft7Validator.check_schema(Model.schema())

This fails with:

SchemaError: [] is not valid under any of the given schemas

Failed validating 'anyOf' in metaschema['properties']['properties']['additionalProperties']['properties']['items']:
    {'anyOf': [{'$ref': '#'}, {'$ref': '#/definitions/schemaArray'}],
     'default': True}

On schema['properties']['f']['items']:
    []

The generated schema is:

{'title': 'Model',
 'type': 'object',
 'properties': {'f': {'title': 'F', 'type': 'array', 'items': []}},
 'required': ['f']}

Is this expected behavior? Would the desired behavior be to set maxItems: 0 and remove items: [] like such (that would make the generated schema valid)?

{'title': 'Model',
 'type': 'object',
 'properties': {'f': {'title': 'F', 'type': 'array', 'maxItems': 0}},
 'required': ['f']}

BTW, glad to see that empty tuples (Tuple[()]) are now supported (https://github.com/samuelcolvin/pydantic/issues/2318)! Thank you 🙏 .

closed time in 18 hours

ghost

pull request commentsamuelcolvin/pydantic

Support discriminated union

please update.

PrettyWood

comment created time in 18 hours

PullRequestReviewEvent
more