Gentoo Archives: gentoo-commits

From: Louis Sautier <sbraz@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: dev-python/pydantic/, dev-python/pydantic/files/
Date: Thu, 08 Oct 2020 19:43:34
Message-Id: 1602186207.b46fa2605f7b0ddc4427f2d601c82eb4a289faef.sbraz@gentoo
1 commit: b46fa2605f7b0ddc4427f2d601c82eb4a289faef
2 Author: Louis Sautier <sbraz <AT> gentoo <DOT> org>
3 AuthorDate: Thu Oct 8 16:30:30 2020 +0000
4 Commit: Louis Sautier <sbraz <AT> gentoo <DOT> org>
5 CommitDate: Thu Oct 8 19:43:27 2020 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=b46fa260
7
8 dev-python/pydantic: new package, v1.6.1, indirect dep. of isort
9
10 Newer versions of dev-python/isort require hypothesis-auto which in turn
11 requires pydantic.
12
13 Package-Manager: Portage-3.0.8, Repoman-3.0.1
14 Signed-off-by: Louis Sautier <sbraz <AT> gentoo.org>
15
16 dev-python/pydantic/Manifest | 1 +
17 .../pydantic/files/pydantic-1.6.1-fix-tests.patch | 45 +++
18 .../pydantic/files/pydantic-1.6.1-py39.patch | 316 +++++++++++++++++++++
19 dev-python/pydantic/metadata.xml | 14 +
20 dev-python/pydantic/pydantic-1.6.1.ebuild | 38 +++
21 5 files changed, 414 insertions(+)
22
23 diff --git a/dev-python/pydantic/Manifest b/dev-python/pydantic/Manifest
24 new file mode 100644
25 index 00000000000..08803723d75
26 --- /dev/null
27 +++ b/dev-python/pydantic/Manifest
28 @@ -0,0 +1 @@
29 +DIST pydantic-1.6.1.tar.gz 244677 BLAKE2B 0a1d6986858ab753cbc4dd262bd268b2a365c241a7de106a7bf21714c6c499c7dbacaea095789d3503507965ca50106da32545be670ed0261827f1fe0316ff67 SHA512 b0442f78a661f56d29697da7e27393261420bdb0f08473d2f7872145a49a18de8c17c903d0899a44263bcd8229e8790161da032dd5a3d5f2dae347c66bd6a567
30
31 diff --git a/dev-python/pydantic/files/pydantic-1.6.1-fix-tests.patch b/dev-python/pydantic/files/pydantic-1.6.1-fix-tests.patch
32 new file mode 100644
33 index 00000000000..1d6dc5d311a
34 --- /dev/null
35 +++ b/dev-python/pydantic/files/pydantic-1.6.1-fix-tests.patch
36 @@ -0,0 +1,45 @@
37 +commit 44eac223df11a1b711ffe0d7946019a173c2a88e
38 +Author: Louis Sautier <sautier.louis@×××××.com>
39 +Date: Thu Oct 8 14:19:58 2020 +0200
40 +
41 + test_config_file_settings_nornir: use less common env. var names
42 +
43 + Gentoo's Portage sets A during the test phase, switching to less common
44 + environment variable names reduces the likelihood of something similar
45 + happening.
46 +
47 +diff --git a/tests/test_settings.py b/tests/test_settings.py
48 +index d24aae3..1f4d678 100644
49 +--- a/tests/test_settings.py
50 ++++ b/tests/test_settings.py
51 +@@ -437,21 +437,21 @@ def test_config_file_settings_nornir(env):
52 + """
53 +
54 + class Settings(BaseSettings):
55 +- a: str
56 +- b: str
57 +- c: str
58 ++ param_a: str
59 ++ param_b: str
60 ++ param_c: str
61 +
62 + def _build_values(self, init_kwargs, _env_file, _env_file_encoding):
63 + config_settings = init_kwargs.pop('__config_settings__')
64 + return {**config_settings, **init_kwargs, **self._build_environ()}
65 +
66 +- env.set('C', 'env setting c')
67 ++ env.set('PARAM_C', 'env setting c')
68 +
69 +- config = {'a': 'config a', 'b': 'config b', 'c': 'config c'}
70 +- s = Settings(__config_settings__=config, b='argument b', c='argument c')
71 +- assert s.a == 'config a'
72 +- assert s.b == 'argument b'
73 +- assert s.c == 'env setting c'
74 ++ config = {'param_a': 'config a', 'param_b': 'config b', 'param_c': 'config c'}
75 ++ s = Settings(__config_settings__=config, param_b='argument b', param_c='argument c')
76 ++ assert s.param_a == 'config a'
77 ++ assert s.param_b == 'argument b'
78 ++ assert s.param_c == 'env setting c'
79 +
80 +
81 + test_env_file = """\
82
83 diff --git a/dev-python/pydantic/files/pydantic-1.6.1-py39.patch b/dev-python/pydantic/files/pydantic-1.6.1-py39.patch
84 new file mode 100644
85 index 00000000000..7cd5290cd59
86 --- /dev/null
87 +++ b/dev-python/pydantic/files/pydantic-1.6.1-py39.patch
88 @@ -0,0 +1,316 @@
89 +diff --git a/changes/1832-PrettyWood.md b/changes/1832-PrettyWood.md
90 +new file mode 100644
91 +index 000000000..5038a0da0
92 +--- /dev/null
93 ++++ b/changes/1832-PrettyWood.md
94 +@@ -0,0 +1 @@
95 ++add basic support of python 3.9
96 +diff --git a/pydantic/fields.py b/pydantic/fields.py
97 +index 01792b628..c52b34ea4 100644
98 +--- a/pydantic/fields.py
99 ++++ b/pydantic/fields.py
100 +@@ -32,6 +32,8 @@
101 + NoArgAnyCallable,
102 + NoneType,
103 + display_as_type,
104 ++ get_args,
105 ++ get_origin,
106 + is_literal_type,
107 + is_new_type,
108 + new_type_supertype,
109 +@@ -411,7 +413,7 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
110 + elif is_literal_type(self.type_):
111 + return
112 +
113 +- origin = getattr(self.type_, '__origin__', None)
114 ++ origin = get_origin(self.type_)
115 + if origin is None:
116 + # field is not "typing" object eg. Union, Dict, List etc.
117 + # allow None for virtual superclasses of NoneType, e.g. Hashable
118 +@@ -422,7 +424,7 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
119 + return
120 + if origin is Union:
121 + types_ = []
122 +- for type_ in self.type_.__args__:
123 ++ for type_ in get_args(self.type_):
124 + if type_ is NoneType:
125 + if self.required is Undefined:
126 + self.required = False
127 +@@ -444,9 +446,9 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
128 + if issubclass(origin, Tuple): # type: ignore
129 + self.shape = SHAPE_TUPLE
130 + self.sub_fields = []
131 +- for i, t in enumerate(self.type_.__args__):
132 ++ for i, t in enumerate(get_args(self.type_)):
133 + if t is Ellipsis:
134 +- self.type_ = self.type_.__args__[0]
135 ++ self.type_ = get_args(self.type_)[0]
136 + self.shape = SHAPE_TUPLE_ELLIPSIS
137 + return
138 + self.sub_fields.append(self._create_sub_type(t, f'{self.name}_{i}'))
139 +@@ -460,7 +462,7 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
140 + {f'list_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
141 + )
142 +
143 +- self.type_ = self.type_.__args__[0]
144 ++ self.type_ = get_args(self.type_)[0]
145 + self.shape = SHAPE_LIST
146 + elif issubclass(origin, Set):
147 + # Create self validators
148 +@@ -470,22 +472,22 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
149 + {f'set_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
150 + )
151 +
152 +- self.type_ = self.type_.__args__[0]
153 ++ self.type_ = get_args(self.type_)[0]
154 + self.shape = SHAPE_SET
155 + elif issubclass(origin, FrozenSet):
156 +- self.type_ = self.type_.__args__[0]
157 ++ self.type_ = get_args(self.type_)[0]
158 + self.shape = SHAPE_FROZENSET
159 + elif issubclass(origin, Sequence):
160 +- self.type_ = self.type_.__args__[0]
161 ++ self.type_ = get_args(self.type_)[0]
162 + self.shape = SHAPE_SEQUENCE
163 + elif issubclass(origin, Mapping):
164 +- self.key_field = self._create_sub_type(self.type_.__args__[0], 'key_' + self.name, for_keys=True)
165 +- self.type_ = self.type_.__args__[1]
166 ++ self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True)
167 ++ self.type_ = get_args(self.type_)[1]
168 + self.shape = SHAPE_MAPPING
169 + # Equality check as almost everything inherits form Iterable, including str
170 + # check for Iterable and CollectionsIterable, as it could receive one even when declared with the other
171 + elif origin in {Iterable, CollectionsIterable}:
172 +- self.type_ = self.type_.__args__[0]
173 ++ self.type_ = get_args(self.type_)[0]
174 + self.shape = SHAPE_ITERABLE
175 + self.sub_fields = [self._create_sub_type(self.type_, f'{self.name}_type')]
176 + elif issubclass(origin, Type): # type: ignore
177 +@@ -494,7 +496,7 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
178 + # Is a Pydantic-compatible generic that handles itself
179 + # or we have arbitrary_types_allowed = True
180 + self.shape = SHAPE_GENERIC
181 +- self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(self.type_.__args__)]
182 ++ self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(get_args(self.type_))]
183 + self.type_ = origin
184 + return
185 + else:
186 +diff --git a/pydantic/generics.py b/pydantic/generics.py
187 +index 64562227d..0a5e75401 100644
188 +--- a/pydantic/generics.py
189 ++++ b/pydantic/generics.py
190 +@@ -3,6 +3,7 @@
191 + from .class_validators import gather_all_validators
192 + from .fields import FieldInfo, ModelField
193 + from .main import BaseModel, create_model
194 ++from .typing import get_origin
195 + from .utils import lenient_issubclass
196 +
197 + _generic_types_cache: Dict[Tuple[Type[Any], Union[Any, Tuple[Any, ...]]], Type[BaseModel]] = {}
198 +@@ -37,7 +38,7 @@ def __class_getitem__(cls: Type[GenericModelT], params: Union[Type[Any], Tuple[T
199 + check_parameters_count(cls, params)
200 + typevars_map: Dict[TypeVarType, Type[Any]] = dict(zip(cls.__parameters__, params))
201 + type_hints = get_type_hints(cls).items()
202 +- instance_type_hints = {k: v for k, v in type_hints if getattr(v, '__origin__', None) is not ClassVar}
203 ++ instance_type_hints = {k: v for k, v in type_hints if get_origin(v) is not ClassVar}
204 + concrete_type_hints: Dict[str, Type[Any]] = {
205 + k: resolve_type_hint(v, typevars_map) for k, v in instance_type_hints.items()
206 + }
207 +@@ -79,7 +80,7 @@ def __concrete_name__(cls: Type[Any], params: Tuple[Type[Any], ...]) -> str:
208 +
209 +
210 + def resolve_type_hint(type_: Any, typevars_map: Dict[Any, Any]) -> Type[Any]:
211 +- if hasattr(type_, '__origin__') and getattr(type_, '__parameters__', None):
212 ++ if get_origin(type_) and getattr(type_, '__parameters__', None):
213 + concrete_type_args = tuple([typevars_map[x] for x in type_.__parameters__])
214 + return type_[concrete_type_args]
215 + return typevars_map.get(type_, type_)
216 +diff --git a/pydantic/main.py b/pydantic/main.py
217 +index c872f1e3b..87299b645 100644
218 +--- a/pydantic/main.py
219 ++++ b/pydantic/main.py
220 +@@ -33,7 +33,7 @@
221 + from .parse import Protocol, load_file, load_str_bytes
222 + from .schema import model_schema
223 + from .types import PyObject, StrBytes
224 +-from .typing import AnyCallable, ForwardRef, is_classvar, resolve_annotations, update_field_forward_refs
225 ++from .typing import AnyCallable, ForwardRef, get_origin, is_classvar, resolve_annotations, update_field_forward_refs
226 + from .utils import (
227 + ClassAttribute,
228 + GetterDict,
229 +@@ -256,7 +256,7 @@ def __new__(mcs, name, bases, namespace, **kwargs): # noqa C901
230 + if (
231 + isinstance(value, untouched_types)
232 + and ann_type != PyObject
233 +- and not lenient_issubclass(getattr(ann_type, '__origin__', None), Type)
234 ++ and not lenient_issubclass(get_origin(ann_type), Type)
235 + ):
236 + continue
237 + fields[ann_name] = inferred = ModelField.infer(
238 +diff --git a/pydantic/schema.py b/pydantic/schema.py
239 +index 27c66b2bd..4f6258ab1 100644
240 +--- a/pydantic/schema.py
241 ++++ b/pydantic/schema.py
242 +@@ -55,7 +55,7 @@
243 + conset,
244 + constr,
245 + )
246 +-from .typing import ForwardRef, Literal, is_callable_type, is_literal_type, literal_values
247 ++from .typing import ForwardRef, Literal, get_args, get_origin, is_callable_type, is_literal_type, literal_values
248 + from .utils import get_model, lenient_issubclass, sequence_like
249 +
250 + if TYPE_CHECKING:
251 +@@ -803,9 +803,9 @@ def go(type_: Any) -> Type[Any]:
252 + or lenient_issubclass(type_, (ConstrainedList, ConstrainedSet))
253 + ):
254 + return type_
255 +- origin = getattr(type_, '__origin__', None)
256 ++ origin = get_origin(type_)
257 + if origin is not None:
258 +- args: Tuple[Any, ...] = type_.__args__
259 ++ args: Tuple[Any, ...] = get_args(type_)
260 + if any(isinstance(a, ForwardRef) for a in args):
261 + # forward refs cause infinite recursion below
262 + return type_
263 +diff --git a/pydantic/typing.py b/pydantic/typing.py
264 +index 070691eeb..729ebd71b 100644
265 +--- a/pydantic/typing.py
266 ++++ b/pydantic/typing.py
267 +@@ -44,12 +44,19 @@ def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
268 + return type_._eval_type(globalns, localns)
269 +
270 +
271 +-else:
272 ++elif sys.version_info < (3, 9):
273 +
274 + def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
275 + return type_._evaluate(globalns, localns)
276 +
277 +
278 ++else:
279 ++
280 ++ # TODO: remove the pragma: no cover once we can run CI on python 3.9
281 ++ def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: # pragma: no cover
282 ++ return type_._evaluate(globalns, localns, set())
283 ++
284 ++
285 + if sys.version_info < (3, 7):
286 + from typing import Callable as Callable
287 +
288 +@@ -70,8 +77,50 @@ def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
289 + from typing_extensions import Literal
290 + except ImportError:
291 + Literal = None
292 ++
293 ++ def get_args(t: Type[Any]) -> Tuple[Any, ...]:
294 ++ return getattr(t, '__args__', ())
295 ++
296 ++ def get_origin(t: Type[Any]) -> Optional[Type[Any]]:
297 ++ return getattr(t, '__origin__', None)
298 ++
299 ++
300 + else:
301 +- from typing import Literal
302 ++ from typing import Literal, get_args as typing_get_args, get_origin as typing_get_origin
303 ++
304 ++ def get_origin(tp: Type[Any]) -> Type[Any]:
305 ++ return typing_get_origin(tp) or getattr(tp, '__origin__', None)
306 ++
307 ++ def generic_get_args(tp: Type[Any]) -> Tuple[Any, ...]:
308 ++ """
309 ++ In python 3.9, `typing.Dict`, `typing.List`, ...
310 ++ do have an empty `__args__` by default (instead of the generic ~T for example).
311 ++ In order to still support `Dict` for example and consider it as `Dict[Any, Any]`,
312 ++ we retrieve the `_nparams` value that tells us how many parameters it needs.
313 ++ """
314 ++ # TODO: remove the pragma: no cover once we can run CI on python 3.9
315 ++ if hasattr(tp, '_nparams'): # pragma: no cover
316 ++ return (Any,) * tp._nparams
317 ++ return ()
318 ++
319 ++ def get_args(tp: Type[Any]) -> Tuple[Any, ...]:
320 ++ """Get type arguments with all substitutions performed.
321 ++
322 ++ For unions, basic simplifications used by Union constructor are performed.
323 ++ Examples::
324 ++ get_args(Dict[str, int]) == (str, int)
325 ++ get_args(int) == ()
326 ++ get_args(Union[int, Union[T, int], str][int]) == (int, str)
327 ++ get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int])
328 ++ get_args(Callable[[], T][int]) == ([], int)
329 ++ """
330 ++ try:
331 ++ args = typing_get_args(tp)
332 ++ # TODO: remove the pragma: no cover once we can run CI on python 3.9
333 ++ except IndexError: # pragma: no cover
334 ++ args = ()
335 ++ return args or getattr(tp, '__args__', ()) or generic_get_args(tp)
336 ++
337 +
338 + if TYPE_CHECKING:
339 + from .fields import ModelField
340 +@@ -115,6 +164,8 @@ def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
341 + 'CallableGenerator',
342 + 'ReprArgs',
343 + 'CallableGenerator',
344 ++ 'get_args',
345 ++ 'get_origin',
346 + )
347 +
348 +
349 +@@ -167,16 +218,16 @@ def resolve_annotations(raw_annotations: Dict[str, Type[Any]], module_name: Opti
350 +
351 +
352 + def is_callable_type(type_: Type[Any]) -> bool:
353 +- return type_ is Callable or getattr(type_, '__origin__', None) is Callable
354 ++ return type_ is Callable or get_origin(type_) is Callable
355 +
356 +
357 + if sys.version_info >= (3, 7):
358 +
359 + def is_literal_type(type_: Type[Any]) -> bool:
360 +- return Literal is not None and getattr(type_, '__origin__', None) is Literal
361 ++ return Literal is not None and get_origin(type_) is Literal
362 +
363 + def literal_values(type_: Type[Any]) -> Tuple[Any, ...]:
364 +- return type_.__args__
365 ++ return get_args(type_)
366 +
367 +
368 + else:
369 +@@ -217,12 +268,15 @@ def new_type_supertype(type_: Type[Any]) -> Type[Any]:
370 + return type_
371 +
372 +
373 +-def _check_classvar(v: Type[Any]) -> bool:
374 ++def _check_classvar(v: Optional[Type[Any]]) -> bool:
375 ++ if v is None:
376 ++ return False
377 ++
378 + return v.__class__ == ClassVar.__class__ and (sys.version_info < (3, 7) or getattr(v, '_name', None) == 'ClassVar')
379 +
380 +
381 + def is_classvar(ann_type: Type[Any]) -> bool:
382 +- return _check_classvar(ann_type) or _check_classvar(getattr(ann_type, '__origin__', None))
383 ++ return _check_classvar(ann_type) or _check_classvar(get_origin(ann_type))
384 +
385 +
386 + def update_field_forward_refs(field: 'ModelField', globalns: Any, localns: Any) -> None:
387 +@@ -243,13 +297,13 @@ def get_class(type_: Type[Any]) -> Union[None, bool, Type[Any]]:
388 + without brackets. Otherwise returns None.
389 + """
390 + try:
391 +- origin = getattr(type_, '__origin__')
392 ++ origin = get_origin(type_)
393 + if origin is None: # Python 3.6
394 + origin = type_
395 + if issubclass(origin, Type): # type: ignore
396 +- if type_.__args__ is None or not isinstance(type_.__args__[0], type):
397 ++ if not get_args(type_) or not isinstance(get_args(type_)[0], type):
398 + return True
399 +- return type_.__args__[0]
400 +- except AttributeError:
401 ++ return get_args(type_)[0]
402 ++ except (AttributeError, TypeError):
403 + pass
404 + return None
405
406 diff --git a/dev-python/pydantic/metadata.xml b/dev-python/pydantic/metadata.xml
407 new file mode 100644
408 index 00000000000..3f626e20bc7
409 --- /dev/null
410 +++ b/dev-python/pydantic/metadata.xml
411 @@ -0,0 +1,14 @@
412 +<?xml version="1.0" encoding="UTF-8"?>
413 +<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
414 +<pkgmetadata>
415 + <maintainer type="project">
416 + <email>python@g.o</email>
417 + <name>Python</name>
418 + </maintainer>
419 + <upstream>
420 + <remote-id type="pypi">pydantic</remote-id>
421 + <remote-id type="github">samuelcolvin/pydantic</remote-id>
422 + <bugs-to>https://github.com/samuelcolvin/pydantic/issues</bugs-to>
423 + <doc>https://pydantic-docs.helpmanual.io/</doc>
424 + </upstream>
425 +</pkgmetadata>
426
427 diff --git a/dev-python/pydantic/pydantic-1.6.1.ebuild b/dev-python/pydantic/pydantic-1.6.1.ebuild
428 new file mode 100644
429 index 00000000000..584f26cc9ec
430 --- /dev/null
431 +++ b/dev-python/pydantic/pydantic-1.6.1.ebuild
432 @@ -0,0 +1,38 @@
433 +# Copyright 1999-2020 Gentoo Authors
434 +# Distributed under the terms of the GNU General Public License v2
435 +
436 +EAPI=7
437 +
438 +# At the moment, PyPy3 doesn't have a dataclasses module
439 +# It can probably be added when PyPy3.7 is stable
440 +PYTHON_COMPAT=( python3_{7..9} )
441 +
442 +inherit distutils-r1
443 +
444 +DESCRIPTION="Data parsing and validation using Python type hints"
445 +HOMEPAGE="https://github.com/samuelcolvin/pydantic"
446 +# No tests on PyPI: https://github.com/samuelcolvin/pydantic/pull/1976
447 +SRC_URI="https://github.com/samuelcolvin/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz"
448 +
449 +LICENSE="MIT"
450 +SLOT="0"
451 +KEYWORDS="~amd64 ~x86"
452 +
453 +BDEPEND="
454 + dev-python/cython[${PYTHON_USEDEP}]
455 +"
456 +
457 +PATCHES=(
458 + # https://github.com/samuelcolvin/pydantic/pull/1977
459 + "${FILESDIR}/${P}-fix-tests.patch"
460 + # https://github.com/samuelcolvin/pydantic/pull/1844
461 + "${FILESDIR}/${P}-py39.patch"
462 +)
463 +
464 +distutils_enable_tests pytest
465 +
466 +python_prepare_all() {
467 + # So we don't need pytest-timeout
468 + sed -i '/^timeout = /d' setup.cfg || die
469 + distutils-r1_python_prepare_all
470 +}