[arch-commits] Commit in cantarell-fonts/repos/extra-any (5 files)

Jan Steffens heftig at archlinux.org
Mon Jan 13 08:38:00 UTC 2020


    Date: Monday, January 13, 2020 @ 08:38:00
  Author: heftig
Revision: 373414

archrelease: copy trunk to extra-any

Added:
  cantarell-fonts/repos/extra-any/PKGBUILD
    (from rev 373413, cantarell-fonts/trunk/PKGBUILD)
  cantarell-fonts/repos/extra-any/cattrs.diff
    (from rev 373413, cantarell-fonts/trunk/cattrs.diff)
Deleted:
  cantarell-fonts/repos/extra-any/PKGBUILD
  cantarell-fonts/repos/extra-any/PKGBUILD.prebuilt
  cantarell-fonts/repos/extra-any/cattrs.diff

-------------------+
 PKGBUILD          |   66 +---
 PKGBUILD.prebuilt |   25 -
 cattrs.diff       |  830 ++++++++++++++++++++++++++--------------------------
 3 files changed, 440 insertions(+), 481 deletions(-)

Deleted: PKGBUILD
===================================================================
--- PKGBUILD	2020-01-13 08:37:46 UTC (rev 373413)
+++ PKGBUILD	2020-01-13 08:38:00 UTC (rev 373414)
@@ -1,41 +0,0 @@
-# Maintainer: Jan Alexander Steffens (heftig) <jan.steffens at gmail.com>
-
-pkgname=cantarell-fonts
-pkgver=0.200
-pkgrel=1
-epoch=1
-pkgdesc="Humanist sans serif font"
-url="https://gitlab.gnome.org/GNOME/cantarell-fonts"
-arch=(any)
-license=(custom:SIL)
-makedepends=(meson appstream-glib git)
-_commit=b4f71a432aec52c250c2b7af4692376659cb085c  # tags/v0.200^0
-source=("git+https://gitlab.gnome.org/GNOME/cantarell-fonts.git#commit=$_commit"
-        cattrs.diff)
-sha256sums=('SKIP'
-            'e6e8cce13fbce7e6923425b6a5de81dd50eadf7ea4b7d6d096cb91648535b214')
-
-pkgver() {
-  cd $pkgname
-  git describe --tags | sed 's/^v//;s/-/+/g'
-}
-
-prepare() {
-  python -m venv venv
-  venv/bin/pip install -r $pkgname/requirements.txt
-
-  # https://github.com/Tinche/cattrs/compare/v0.9.0..v1.0.0
-  patch -d venv/lib/python3.8/site-packages -Np2 < cattrs.diff
-}
-
-build() {
-  PATH="$srcdir/venv/bin:$PATH" arch-meson $pkgname build
-  ninja -C build
-}
-
-package() {
-  DESTDIR="$pkgdir" meson install -C build
-  install -Dt "$pkgdir/usr/share/licenses/$pkgname" -m644 $pkgname/COPYING
-}
-
-# vim:set ts=2 sw=2 et:

Copied: cantarell-fonts/repos/extra-any/PKGBUILD (from rev 373413, cantarell-fonts/trunk/PKGBUILD)
===================================================================
--- PKGBUILD	                        (rev 0)
+++ PKGBUILD	2020-01-13 08:38:00 UTC (rev 373414)
@@ -0,0 +1,25 @@
+# Maintainer: Jan Alexander Steffens (heftig) <jan.steffens at gmail.com>
+
+pkgname=cantarell-fonts
+pkgver=0.201
+pkgrel=1
+epoch=1
+pkgdesc="Humanist sans serif font"
+url="https://gitlab.gnome.org/GNOME/cantarell-fonts"
+arch=(any)
+license=(custom:SIL)
+makedepends=(meson appstream-glib git)
+source=("https://download.gnome.org/sources/$pkgname/$pkgver/$pkgname-$pkgver.tar.xz")
+sha256sums=('b61f64e5f6a48aa0abc7a53cdcbce60de81908ca36048a64730978fcd9ac9863')
+
+build() {
+  arch-meson $pkgname-$pkgver build -D useprebuilt=true
+  ninja -C build
+}
+
+package() {
+  DESTDIR="$pkgdir" meson install -C build
+  install -Dt "$pkgdir/usr/share/licenses/$pkgname" -m644 $pkgname-$pkgver/COPYING
+}
+
+# vim:set ts=2 sw=2 et:

Deleted: PKGBUILD.prebuilt
===================================================================
--- PKGBUILD.prebuilt	2020-01-13 08:37:46 UTC (rev 373413)
+++ PKGBUILD.prebuilt	2020-01-13 08:38:00 UTC (rev 373414)
@@ -1,25 +0,0 @@
-# Maintainer: Jan Alexander Steffens (heftig) <jan.steffens at gmail.com>
-
-pkgname=cantarell-fonts
-pkgver=0.200
-pkgrel=1
-epoch=1
-pkgdesc="Humanist sans serif font"
-url="https://gitlab.gnome.org/GNOME/cantarell-fonts"
-arch=(any)
-license=(custom:SIL)
-makedepends=(meson appstream-glib git)
-source=("https://download.gnome.org/sources/$pkgname/$pkgver/$pkgname-$pkgver.tar.xz")
-sha256sums=('a30131f7ab9d78e70415a7f601cbcc443ff5bcc44b0332ddc84d8624ba177661')
-
-build() {
-  arch-meson $pkgname-$pkgver build -D useprebuilt=true
-  ninja -C build
-}
-
-package() {
-  DESTDIR="$pkgdir" meson install -C build
-  install -Dt "$pkgdir/usr/share/licenses/$pkgname" -m644 $pkgname-$pkgver/COPYING
-}
-
-# vim:set ts=2 sw=2 et:

Deleted: cattrs.diff
===================================================================
--- cattrs.diff	2020-01-13 08:37:46 UTC (rev 373413)
+++ cattrs.diff	2020-01-13 08:38:00 UTC (rev 373414)
@@ -1,415 +0,0 @@
-diff --git a/src/cattr/_compat.py b/src/cattr/_compat.py
-index 73d81d5..7cd4c54 100644
---- a/src/cattr/_compat.py
-+++ b/src/cattr/_compat.py
-@@ -13,20 +13,21 @@ version_info = sys.version_info[0:3]
- is_py2 = version_info[0] == 2
- is_py3 = version_info[0] == 3
- is_py37 = version_info[:2] == (3, 7)
-+is_py38 = version_info[:2] == (3, 8)
- 
- if is_py2:
-     from functools32 import lru_cache
-     from singledispatch import singledispatch
- 
-     unicode = unicode  # noqa
-     bytes = str
- else:
-     from functools import lru_cache, singledispatch  # noqa
- 
-     unicode = str
-     bytes = bytes
- 
--if is_py37:
-+if is_py37 or is_py38:
-     from typing import List, Union, _GenericAlias
- 
-     def is_union_type(obj):
-@@ -96,7 +97,11 @@ else:
-         return issubclass(type, MutableSet)
- 
-     def is_sequence(type):
--        return issubclass(type, Sequence)
-+        if is_py2:
-+            is_string = issubclass(type, basestring)  # noqa:F821
-+        else:
-+            is_string = issubclass(type, str)
-+        return issubclass(type, Sequence) and not is_string
- 
-     def is_tuple(type):
-         return issubclass(type, Tuple)
-diff --git a/src/cattr/converters.py b/src/cattr/converters.py
-index 57b9f4d..24b039c 100644
---- a/src/cattr/converters.py
-+++ b/src/cattr/converters.py
-@@ -1,5 +1,17 @@
- from enum import Enum
--from typing import Mapping, Sequence, Optional, TypeVar, Any
-+from typing import (  # noqa: F401, imported for Mypy.
-+    Any,
-+    Callable,
-+    Dict,
-+    FrozenSet,
-+    Mapping,
-+    Optional,
-+    Sequence,
-+    Set,
-+    Tuple,
-+    Type,
-+    TypeVar,
-+)
- from ._compat import (
-     bytes,
-     is_bare,
-@@ -79,6 +91,8 @@ class Converter(object):
-             [
-                 (_subclass(Mapping), self._unstructure_mapping),
-                 (_subclass(Sequence), self._unstructure_seq),
-+                (_subclass(Set), self._unstructure_seq),
-+                (_subclass(FrozenSet), self._unstructure_seq),
-                 (_subclass(Enum), self._unstructure_enum),
-                 (_is_attrs_class, self._unstructure_attrs),
-             ]
-@@ -121,95 +135,96 @@ class Converter(object):
-         self._union_registry = {}
- 
-     def unstructure(self, obj):
-+        # type: (Any) -> Any
-         return self._unstructure_func.dispatch(obj.__class__)(obj)
- 
-     @property
-     def unstruct_strat(self):
-         # type: () -> UnstructureStrategy
-         """The default way of unstructuring ``attrs`` classes."""
-         return (
-             UnstructureStrategy.AS_DICT
-             if self._unstructure_attrs == self.unstructure_attrs_asdict
-             else UnstructureStrategy.AS_TUPLE
-         )
- 
-     def register_unstructure_hook(self, cls, func):
-         # type: (Type[T], Callable[[T], Any]) -> None
-         """Register a class-to-primitive converter function for a class.
- 
-         The converter function should take an instance of the class and return
-         its Python equivalent.
-         """
-         self._unstructure_func.register_cls_list([(cls, func)])
- 
-     def register_unstructure_hook_func(self, check_func, func):
-         """Register a class-to-primitive converter function for a class, using
-         a function to check if it's a match.
-         """
--        # type: (Callable[Any], Callable[T], Any]) -> None
-         self._unstructure_func.register_func_list([(check_func, func)])
- 
-     def register_structure_hook(self, cl, func):
-         """Register a primitive-to-class converter function for a type.
- 
-         The converter function should take two arguments:
-           * a Python object to be converted,
-           * the type to convert to
- 
-         and return the instance of the class. The type may seem redundant, but
-         is sometimes needed (for example, when dealing with generic classes).
-         """
--        # type: (Type[T], Callable[[Any, Type], T) -> None
-         if is_union_type(cl):
-             self._union_registry[cl] = func
-         else:
-             self._structure_func.register_cls_list([(cl, func)])
- 
-     def register_structure_hook_func(self, check_func, func):
--        # type: (Callable[Any], Callable[T], Any]) -> None
-+        # type: (Callable[[Any], Any], Callable[[T], Any]) -> None
-         """Register a class-to-primitive converter function for a class, using
-         a function to check if it's a match.
-         """
-         self._structure_func.register_func_list([(check_func, func)])
- 
-     def structure(self, obj, cl):
-+        # type: (Any, Type[T]) -> T
-         """Convert unstructured Python data structures to structured data."""
--        # type: (Any, Type) -> Any
-+
-         return self._structure_func.dispatch(cl)(obj, cl)
- 
-     # Classes to Python primitives.
-     def unstructure_attrs_asdict(self, obj):
-+        # type: (Any) -> Dict[str, Any]
-         """Our version of `attrs.asdict`, so we can call back to us."""
-         attrs = obj.__class__.__attrs_attrs__
-         dispatch = self._unstructure_func.dispatch
-         rv = self._dict_factory()
-         for a in attrs:
-             name = a.name
-             v = getattr(obj, name)
-             rv[name] = dispatch(v.__class__)(v)
-         return rv
- 
-     def unstructure_attrs_astuple(self, obj):
-+        # type: (Any) -> Tuple
-         """Our version of `attrs.astuple`, so we can call back to us."""
-         attrs = obj.__class__.__attrs_attrs__
-         return tuple(self.unstructure(getattr(obj, a.name)) for a in attrs)
- 
-     def _unstructure_enum(self, obj):
-         """Convert an enum to its value."""
-         return obj.value
- 
-     def _unstructure_identity(self, obj):
-         """Just pass it through."""
-         return obj
- 
-     def _unstructure_seq(self, seq):
-         """Convert a sequence to primitive equivalents."""
-         # We can reuse the sequence class, so tuples stay tuples.
-         dispatch = self._unstructure_func.dispatch
-         return seq.__class__(dispatch(e.__class__)(e) for e in seq)
- 
-     def _unstructure_mapping(self, mapping):
--        # type: (Mapping) -> Any
-         """Convert a mapping of attr classes to primitive equivalents."""
- 
-         # We can reuse the mapping class, so dicts stay dicts and OrderedDicts
-@@ -258,159 +273,159 @@ class Converter(object):
-     # Attrs classes.
- 
-     def structure_attrs_fromtuple(self, obj, cl):
--        # type: (Sequence[Any], Type) -> Any
-+        # type: (Tuple, Type[T]) -> T
-         """Load an attrs class from a sequence (tuple)."""
-         conv_obj = []  # A list of converter parameters.
--        for a, value in zip(cl.__attrs_attrs__, obj):
-+        for a, value in zip(cl.__attrs_attrs__, obj):  # type: ignore
-             # We detect the type by the metadata.
-             converted = self._structure_attr_from_tuple(a, a.name, value)
-             conv_obj.append(converted)
- 
--        return cl(*conv_obj)
-+        return cl(*conv_obj)  # type: ignore
- 
-     def _structure_attr_from_tuple(self, a, name, value):
-         """Handle an individual attrs attribute."""
-         type_ = a.type
-         if type_ is None:
-             # No type metadata.
-             return value
-         return self._structure_func.dispatch(type_)(value, type_)
- 
-     def structure_attrs_fromdict(self, obj, cl):
--        # type: (Mapping, Type) -> Any
-+        # type: (Mapping[str, Any], Type[T]) -> T
-         """Instantiate an attrs class from a mapping (dict)."""
-         # For public use.
--        conv_obj = obj.copy()  # Dict of converted parameters.
-+        conv_obj = {}  # Start with a fresh dict, to ignore extra keys.
-         dispatch = self._structure_func.dispatch
--        for a in cl.__attrs_attrs__:
-+        for a in cl.__attrs_attrs__:  # type: ignore
-             # We detect the type by metadata.
-             type_ = a.type
--            if type_ is None:
--                # No type.
--                continue
-             name = a.name
-+
-             try:
-                 val = obj[name]
-             except KeyError:
-                 continue
--            conv_obj[name] = dispatch(type_)(val, type_)
- 
--        return cl(**conv_obj)
-+            if name[0] == "_":
-+                name = name[1:]
-+
-+            conv_obj[name] = (
-+                dispatch(type_)(val, type_) if type_ is not None else val
-+            )
-+
-+        return cl(**conv_obj)  # type: ignore
- 
-     def _structure_list(self, obj, cl):
--        # type: (Type[GenericMeta], Iterable[T]) -> List[T]
-         """Convert an iterable to a potentially generic list."""
-         if is_bare(cl) or cl.__args__[0] is Any:
-             return [e for e in obj]
-         else:
-             elem_type = cl.__args__[0]
-             return [
-                 self._structure_func.dispatch(elem_type)(e, elem_type)
-                 for e in obj
-             ]
- 
-     def _structure_set(self, obj, cl):
--        # type: (Type[GenericMeta], Iterable[T]) -> MutableSet[T]
-         """Convert an iterable into a potentially generic set."""
-         if is_bare(cl) or cl.__args__[0] is Any:
-             return set(obj)
-         else:
-             elem_type = cl.__args__[0]
-             return {
-                 self._structure_func.dispatch(elem_type)(e, elem_type)
-                 for e in obj
-             }
- 
-     def _structure_frozenset(self, obj, cl):
--        # type: (Type[GenericMeta], Iterable[T]) -> FrozenSet[T]
-         """Convert an iterable into a potentially generic frozenset."""
-         if is_bare(cl) or cl.__args__[0] is Any:
-             return frozenset(obj)
-         else:
-             elem_type = cl.__args__[0]
-             dispatch = self._structure_func.dispatch
-             return frozenset(dispatch(elem_type)(e, elem_type) for e in obj)
- 
-     def _structure_dict(self, obj, cl):
--        # type: (Type[GenericMeta], Mapping[T, V]) -> Dict[T, V]
-         """Convert a mapping into a potentially generic dict."""
-         if is_bare(cl) or cl.__args__ == (Any, Any):
-             return dict(obj)
-         else:
-             key_type, val_type = cl.__args__
-             if key_type is Any:
-                 val_conv = self._structure_func.dispatch(val_type)
-                 return {k: val_conv(v, val_type) for k, v in obj.items()}
-             elif val_type is Any:
-                 key_conv = self._structure_func.dispatch(key_type)
-                 return {key_conv(k, key_type): v for k, v in obj.items()}
-             else:
-                 key_conv = self._structure_func.dispatch(key_type)
-                 val_conv = self._structure_func.dispatch(val_type)
-                 return {
-                     key_conv(k, key_type): val_conv(v, val_type)
-                     for k, v in obj.items()
-                 }
- 
-     def _structure_union(self, obj, union):
--        # type: (_Union, Any): -> Any
-         """Deal with converting a union."""
-         # Unions with NoneType in them are basically optionals.
-         # We check for NoneType early and handle the case of obj being None,
-         # so disambiguation functions don't need to handle NoneType.
-         union_params = union.__args__
--        if NoneType in union_params:
-+        if NoneType in union_params:  # type: ignore
-             if obj is None:
-                 return None
-             if len(union_params) == 2:
-                 # This is just a NoneType and something else.
-                 other = (
-                     union_params[0]
--                    if union_params[1] is NoneType
-+                    if union_params[1] is NoneType  # type: ignore
-                     else union_params[1]
-                 )
-                 # We can't actually have a Union of a Union, so this is safe.
-                 return self._structure_func.dispatch(other)(obj, other)
- 
-         # Check the union registry first.
-         handler = self._union_registry.get(union)
-         if handler is not None:
-             return handler(obj, union)
- 
-         # Getting here means either this is not an optional, or it's an
-         # optional with more than one parameter.
-         # Let's support only unions of attr classes for now.
-         cl = self._dis_func_cache(union)(obj)
-         return self._structure_func.dispatch(cl)(obj, cl)
- 
-     def _structure_tuple(self, obj, tup):
--        # type: (Type[Tuple], Iterable) -> Any
-         """Deal with converting to a tuple."""
-         tup_params = tup.__args__
-         has_ellipsis = tup_params and tup_params[-1] is Ellipsis
-         if tup_params is None or (has_ellipsis and tup_params[0] is Any):
-             # Just a Tuple. (No generic information.)
-             return tuple(obj)
-         if has_ellipsis:
-             # We're dealing with a homogenous tuple, Tuple[int, ...]
-             tup_type = tup_params[0]
-             conv = self._structure_func.dispatch(tup_type)
-             return tuple(conv(e, tup_type) for e in obj)
-         else:
-             # We're dealing with a heterogenous tuple.
-             return tuple(
-                 self._structure_func.dispatch(t)(e, t)
-                 for t, e in zip(tup_params, obj)
-             )
- 
-     def _get_dis_func(self, union):
-         # type: (Type) -> Callable[..., Type]
-         """Fetch or try creating a disambiguation function for a union."""
-         union_types = union.__args__
--        if NoneType in union_types:
-+        if NoneType in union_types:  # type: ignore
-             # We support unions of attrs classes and NoneType higher in the
-             # logic.
--            union_types = tuple(e for e in union_types if e is not NoneType)
-+            union_types = tuple(
-+                e for e in union_types if e is not NoneType  # type: ignore
-+            )
- 
-         if not all(hasattr(e, "__attrs_attrs__") for e in union_types):
-             raise ValueError(
-diff --git a/src/cattr/disambiguators.py b/src/cattr/disambiguators.py
-index 4daa078..765a630 100644
---- a/src/cattr/disambiguators.py
-+++ b/src/cattr/disambiguators.py
-@@ -3,42 +3,48 @@ from collections import OrderedDict
- from functools import reduce
- from operator import or_
- 
--from typing import Mapping
-+from typing import (  # noqa: F401, imported for Mypy.
-+    Callable,
-+    Dict,
-+    Mapping,
-+    Optional,
-+    Type,
-+)
- 
- from attr import fields
- 
- 
--def create_uniq_field_dis_func(*cls):
--    # type: (*Sequence[Type]) -> Callable
-+def create_uniq_field_dis_func(*classes):
-+    # type: (*Type) -> Callable
-     """Given attr classes, generate a disambiguation function.
- 
-     The function is based on unique fields."""
--    if len(cls) < 2:
-+    if len(classes) < 2:
-         raise ValueError("At least two classes required.")
--    cls_and_attrs = [(cl, set(at.name for at in fields(cl))) for cl in cls]
-+    cls_and_attrs = [(cl, set(at.name for at in fields(cl))) for cl in classes]
-     if len([attrs for _, attrs in cls_and_attrs if len(attrs) == 0]) > 1:
-         raise ValueError("At least two classes have no attributes.")
-     # TODO: Deal with a single class having no required attrs.
-     # For each class, attempt to generate a single unique required field.
--    uniq_attrs_dict = OrderedDict()
-+    uniq_attrs_dict = OrderedDict()  # type: Dict[str, Type]
-     cls_and_attrs.sort(key=lambda c_a: -len(c_a[1]))
- 
-     fallback = None  # If none match, try this.
- 
-     for i, (cl, cl_reqs) in enumerate(cls_and_attrs):
-         other_classes = cls_and_attrs[i + 1 :]
-         if other_classes:
-             other_reqs = reduce(or_, (c_a[1] for c_a in other_classes))
-             uniq = cl_reqs - other_reqs
-             if not uniq:
-                 m = "{} has no usable unique attributes.".format(cl)
-                 raise ValueError(m)
-             uniq_attrs_dict[next(iter(uniq))] = cl
-         else:
-             fallback = cl
- 
-     def dis_func(data):
--        # type: (Mapping) -> Union
-+        # type: (Mapping) -> Optional[Type]
-         if not isinstance(data, Mapping):
-             raise ValueError("Only input mappings are supported.")
-         for k, v in uniq_attrs_dict.items():

Copied: cantarell-fonts/repos/extra-any/cattrs.diff (from rev 373413, cantarell-fonts/trunk/cattrs.diff)
===================================================================
--- cattrs.diff	                        (rev 0)
+++ cattrs.diff	2020-01-13 08:38:00 UTC (rev 373414)
@@ -0,0 +1,415 @@
+diff --git a/src/cattr/_compat.py b/src/cattr/_compat.py
+index 73d81d5..7cd4c54 100644
+--- a/src/cattr/_compat.py
++++ b/src/cattr/_compat.py
+@@ -13,20 +13,21 @@ version_info = sys.version_info[0:3]
+ is_py2 = version_info[0] == 2
+ is_py3 = version_info[0] == 3
+ is_py37 = version_info[:2] == (3, 7)
++is_py38 = version_info[:2] == (3, 8)
+ 
+ if is_py2:
+     from functools32 import lru_cache
+     from singledispatch import singledispatch
+ 
+     unicode = unicode  # noqa
+     bytes = str
+ else:
+     from functools import lru_cache, singledispatch  # noqa
+ 
+     unicode = str
+     bytes = bytes
+ 
+-if is_py37:
++if is_py37 or is_py38:
+     from typing import List, Union, _GenericAlias
+ 
+     def is_union_type(obj):
+@@ -96,7 +97,11 @@ else:
+         return issubclass(type, MutableSet)
+ 
+     def is_sequence(type):
+-        return issubclass(type, Sequence)
++        if is_py2:
++            is_string = issubclass(type, basestring)  # noqa:F821
++        else:
++            is_string = issubclass(type, str)
++        return issubclass(type, Sequence) and not is_string
+ 
+     def is_tuple(type):
+         return issubclass(type, Tuple)
+diff --git a/src/cattr/converters.py b/src/cattr/converters.py
+index 57b9f4d..24b039c 100644
+--- a/src/cattr/converters.py
++++ b/src/cattr/converters.py
+@@ -1,5 +1,17 @@
+ from enum import Enum
+-from typing import Mapping, Sequence, Optional, TypeVar, Any
++from typing import (  # noqa: F401, imported for Mypy.
++    Any,
++    Callable,
++    Dict,
++    FrozenSet,
++    Mapping,
++    Optional,
++    Sequence,
++    Set,
++    Tuple,
++    Type,
++    TypeVar,
++)
+ from ._compat import (
+     bytes,
+     is_bare,
+@@ -79,6 +91,8 @@ class Converter(object):
+             [
+                 (_subclass(Mapping), self._unstructure_mapping),
+                 (_subclass(Sequence), self._unstructure_seq),
++                (_subclass(Set), self._unstructure_seq),
++                (_subclass(FrozenSet), self._unstructure_seq),
+                 (_subclass(Enum), self._unstructure_enum),
+                 (_is_attrs_class, self._unstructure_attrs),
+             ]
+@@ -121,95 +135,96 @@ class Converter(object):
+         self._union_registry = {}
+ 
+     def unstructure(self, obj):
++        # type: (Any) -> Any
+         return self._unstructure_func.dispatch(obj.__class__)(obj)
+ 
+     @property
+     def unstruct_strat(self):
+         # type: () -> UnstructureStrategy
+         """The default way of unstructuring ``attrs`` classes."""
+         return (
+             UnstructureStrategy.AS_DICT
+             if self._unstructure_attrs == self.unstructure_attrs_asdict
+             else UnstructureStrategy.AS_TUPLE
+         )
+ 
+     def register_unstructure_hook(self, cls, func):
+         # type: (Type[T], Callable[[T], Any]) -> None
+         """Register a class-to-primitive converter function for a class.
+ 
+         The converter function should take an instance of the class and return
+         its Python equivalent.
+         """
+         self._unstructure_func.register_cls_list([(cls, func)])
+ 
+     def register_unstructure_hook_func(self, check_func, func):
+         """Register a class-to-primitive converter function for a class, using
+         a function to check if it's a match.
+         """
+-        # type: (Callable[Any], Callable[T], Any]) -> None
+         self._unstructure_func.register_func_list([(check_func, func)])
+ 
+     def register_structure_hook(self, cl, func):
+         """Register a primitive-to-class converter function for a type.
+ 
+         The converter function should take two arguments:
+           * a Python object to be converted,
+           * the type to convert to
+ 
+         and return the instance of the class. The type may seem redundant, but
+         is sometimes needed (for example, when dealing with generic classes).
+         """
+-        # type: (Type[T], Callable[[Any, Type], T) -> None
+         if is_union_type(cl):
+             self._union_registry[cl] = func
+         else:
+             self._structure_func.register_cls_list([(cl, func)])
+ 
+     def register_structure_hook_func(self, check_func, func):
+-        # type: (Callable[Any], Callable[T], Any]) -> None
++        # type: (Callable[[Any], Any], Callable[[T], Any]) -> None
+         """Register a class-to-primitive converter function for a class, using
+         a function to check if it's a match.
+         """
+         self._structure_func.register_func_list([(check_func, func)])
+ 
+     def structure(self, obj, cl):
++        # type: (Any, Type[T]) -> T
+         """Convert unstructured Python data structures to structured data."""
+-        # type: (Any, Type) -> Any
++
+         return self._structure_func.dispatch(cl)(obj, cl)
+ 
+     # Classes to Python primitives.
+     def unstructure_attrs_asdict(self, obj):
++        # type: (Any) -> Dict[str, Any]
+         """Our version of `attrs.asdict`, so we can call back to us."""
+         attrs = obj.__class__.__attrs_attrs__
+         dispatch = self._unstructure_func.dispatch
+         rv = self._dict_factory()
+         for a in attrs:
+             name = a.name
+             v = getattr(obj, name)
+             rv[name] = dispatch(v.__class__)(v)
+         return rv
+ 
+     def unstructure_attrs_astuple(self, obj):
++        # type: (Any) -> Tuple
+         """Our version of `attrs.astuple`, so we can call back to us."""
+         attrs = obj.__class__.__attrs_attrs__
+         return tuple(self.unstructure(getattr(obj, a.name)) for a in attrs)
+ 
+     def _unstructure_enum(self, obj):
+         """Convert an enum to its value."""
+         return obj.value
+ 
+     def _unstructure_identity(self, obj):
+         """Just pass it through."""
+         return obj
+ 
+     def _unstructure_seq(self, seq):
+         """Convert a sequence to primitive equivalents."""
+         # We can reuse the sequence class, so tuples stay tuples.
+         dispatch = self._unstructure_func.dispatch
+         return seq.__class__(dispatch(e.__class__)(e) for e in seq)
+ 
+     def _unstructure_mapping(self, mapping):
+-        # type: (Mapping) -> Any
+         """Convert a mapping of attr classes to primitive equivalents."""
+ 
+         # We can reuse the mapping class, so dicts stay dicts and OrderedDicts
+@@ -258,159 +273,159 @@ class Converter(object):
+     # Attrs classes.
+ 
+     def structure_attrs_fromtuple(self, obj, cl):
+-        # type: (Sequence[Any], Type) -> Any
++        # type: (Tuple, Type[T]) -> T
+         """Load an attrs class from a sequence (tuple)."""
+         conv_obj = []  # A list of converter parameters.
+-        for a, value in zip(cl.__attrs_attrs__, obj):
++        for a, value in zip(cl.__attrs_attrs__, obj):  # type: ignore
+             # We detect the type by the metadata.
+             converted = self._structure_attr_from_tuple(a, a.name, value)
+             conv_obj.append(converted)
+ 
+-        return cl(*conv_obj)
++        return cl(*conv_obj)  # type: ignore
+ 
+     def _structure_attr_from_tuple(self, a, name, value):
+         """Handle an individual attrs attribute."""
+         type_ = a.type
+         if type_ is None:
+             # No type metadata.
+             return value
+         return self._structure_func.dispatch(type_)(value, type_)
+ 
+     def structure_attrs_fromdict(self, obj, cl):
+-        # type: (Mapping, Type) -> Any
++        # type: (Mapping[str, Any], Type[T]) -> T
+         """Instantiate an attrs class from a mapping (dict)."""
+         # For public use.
+-        conv_obj = obj.copy()  # Dict of converted parameters.
++        conv_obj = {}  # Start with a fresh dict, to ignore extra keys.
+         dispatch = self._structure_func.dispatch
+-        for a in cl.__attrs_attrs__:
++        for a in cl.__attrs_attrs__:  # type: ignore
+             # We detect the type by metadata.
+             type_ = a.type
+-            if type_ is None:
+-                # No type.
+-                continue
+             name = a.name
++
+             try:
+                 val = obj[name]
+             except KeyError:
+                 continue
+-            conv_obj[name] = dispatch(type_)(val, type_)
+ 
+-        return cl(**conv_obj)
++            if name[0] == "_":
++                name = name[1:]
++
++            conv_obj[name] = (
++                dispatch(type_)(val, type_) if type_ is not None else val
++            )
++
++        return cl(**conv_obj)  # type: ignore
+ 
+     def _structure_list(self, obj, cl):
+-        # type: (Type[GenericMeta], Iterable[T]) -> List[T]
+         """Convert an iterable to a potentially generic list."""
+         if is_bare(cl) or cl.__args__[0] is Any:
+             return [e for e in obj]
+         else:
+             elem_type = cl.__args__[0]
+             return [
+                 self._structure_func.dispatch(elem_type)(e, elem_type)
+                 for e in obj
+             ]
+ 
+     def _structure_set(self, obj, cl):
+-        # type: (Type[GenericMeta], Iterable[T]) -> MutableSet[T]
+         """Convert an iterable into a potentially generic set."""
+         if is_bare(cl) or cl.__args__[0] is Any:
+             return set(obj)
+         else:
+             elem_type = cl.__args__[0]
+             return {
+                 self._structure_func.dispatch(elem_type)(e, elem_type)
+                 for e in obj
+             }
+ 
+     def _structure_frozenset(self, obj, cl):
+-        # type: (Type[GenericMeta], Iterable[T]) -> FrozenSet[T]
+         """Convert an iterable into a potentially generic frozenset."""
+         if is_bare(cl) or cl.__args__[0] is Any:
+             return frozenset(obj)
+         else:
+             elem_type = cl.__args__[0]
+             dispatch = self._structure_func.dispatch
+             return frozenset(dispatch(elem_type)(e, elem_type) for e in obj)
+ 
+     def _structure_dict(self, obj, cl):
+-        # type: (Type[GenericMeta], Mapping[T, V]) -> Dict[T, V]
+         """Convert a mapping into a potentially generic dict."""
+         if is_bare(cl) or cl.__args__ == (Any, Any):
+             return dict(obj)
+         else:
+             key_type, val_type = cl.__args__
+             if key_type is Any:
+                 val_conv = self._structure_func.dispatch(val_type)
+                 return {k: val_conv(v, val_type) for k, v in obj.items()}
+             elif val_type is Any:
+                 key_conv = self._structure_func.dispatch(key_type)
+                 return {key_conv(k, key_type): v for k, v in obj.items()}
+             else:
+                 key_conv = self._structure_func.dispatch(key_type)
+                 val_conv = self._structure_func.dispatch(val_type)
+                 return {
+                     key_conv(k, key_type): val_conv(v, val_type)
+                     for k, v in obj.items()
+                 }
+ 
+     def _structure_union(self, obj, union):
+-        # type: (_Union, Any): -> Any
+         """Deal with converting a union."""
+         # Unions with NoneType in them are basically optionals.
+         # We check for NoneType early and handle the case of obj being None,
+         # so disambiguation functions don't need to handle NoneType.
+         union_params = union.__args__
+-        if NoneType in union_params:
++        if NoneType in union_params:  # type: ignore
+             if obj is None:
+                 return None
+             if len(union_params) == 2:
+                 # This is just a NoneType and something else.
+                 other = (
+                     union_params[0]
+-                    if union_params[1] is NoneType
++                    if union_params[1] is NoneType  # type: ignore
+                     else union_params[1]
+                 )
+                 # We can't actually have a Union of a Union, so this is safe.
+                 return self._structure_func.dispatch(other)(obj, other)
+ 
+         # Check the union registry first.
+         handler = self._union_registry.get(union)
+         if handler is not None:
+             return handler(obj, union)
+ 
+         # Getting here means either this is not an optional, or it's an
+         # optional with more than one parameter.
+         # Let's support only unions of attr classes for now.
+         cl = self._dis_func_cache(union)(obj)
+         return self._structure_func.dispatch(cl)(obj, cl)
+ 
+     def _structure_tuple(self, obj, tup):
+-        # type: (Type[Tuple], Iterable) -> Any
+         """Deal with converting to a tuple."""
+         tup_params = tup.__args__
+         has_ellipsis = tup_params and tup_params[-1] is Ellipsis
+         if tup_params is None or (has_ellipsis and tup_params[0] is Any):
+             # Just a Tuple. (No generic information.)
+             return tuple(obj)
+         if has_ellipsis:
+             # We're dealing with a homogenous tuple, Tuple[int, ...]
+             tup_type = tup_params[0]
+             conv = self._structure_func.dispatch(tup_type)
+             return tuple(conv(e, tup_type) for e in obj)
+         else:
+             # We're dealing with a heterogenous tuple.
+             return tuple(
+                 self._structure_func.dispatch(t)(e, t)
+                 for t, e in zip(tup_params, obj)
+             )
+ 
+     def _get_dis_func(self, union):
+         # type: (Type) -> Callable[..., Type]
+         """Fetch or try creating a disambiguation function for a union."""
+         union_types = union.__args__
+-        if NoneType in union_types:
++        if NoneType in union_types:  # type: ignore
+             # We support unions of attrs classes and NoneType higher in the
+             # logic.
+-            union_types = tuple(e for e in union_types if e is not NoneType)
++            union_types = tuple(
++                e for e in union_types if e is not NoneType  # type: ignore
++            )
+ 
+         if not all(hasattr(e, "__attrs_attrs__") for e in union_types):
+             raise ValueError(
+diff --git a/src/cattr/disambiguators.py b/src/cattr/disambiguators.py
+index 4daa078..765a630 100644
+--- a/src/cattr/disambiguators.py
++++ b/src/cattr/disambiguators.py
+@@ -3,42 +3,48 @@ from collections import OrderedDict
+ from functools import reduce
+ from operator import or_
+ 
+-from typing import Mapping
++from typing import (  # noqa: F401, imported for Mypy.
++    Callable,
++    Dict,
++    Mapping,
++    Optional,
++    Type,
++)
+ 
+ from attr import fields
+ 
+ 
+-def create_uniq_field_dis_func(*cls):
+-    # type: (*Sequence[Type]) -> Callable
++def create_uniq_field_dis_func(*classes):
++    # type: (*Type) -> Callable
+     """Given attr classes, generate a disambiguation function.
+ 
+     The function is based on unique fields."""
+-    if len(cls) < 2:
++    if len(classes) < 2:
+         raise ValueError("At least two classes required.")
+-    cls_and_attrs = [(cl, set(at.name for at in fields(cl))) for cl in cls]
++    cls_and_attrs = [(cl, set(at.name for at in fields(cl))) for cl in classes]
+     if len([attrs for _, attrs in cls_and_attrs if len(attrs) == 0]) > 1:
+         raise ValueError("At least two classes have no attributes.")
+     # TODO: Deal with a single class having no required attrs.
+     # For each class, attempt to generate a single unique required field.
+-    uniq_attrs_dict = OrderedDict()
++    uniq_attrs_dict = OrderedDict()  # type: Dict[str, Type]
+     cls_and_attrs.sort(key=lambda c_a: -len(c_a[1]))
+ 
+     fallback = None  # If none match, try this.
+ 
+     for i, (cl, cl_reqs) in enumerate(cls_and_attrs):
+         other_classes = cls_and_attrs[i + 1 :]
+         if other_classes:
+             other_reqs = reduce(or_, (c_a[1] for c_a in other_classes))
+             uniq = cl_reqs - other_reqs
+             if not uniq:
+                 m = "{} has no usable unique attributes.".format(cl)
+                 raise ValueError(m)
+             uniq_attrs_dict[next(iter(uniq))] = cl
+         else:
+             fallback = cl
+ 
+     def dis_func(data):
+-        # type: (Mapping) -> Union
++        # type: (Mapping) -> Optional[Type]
+         if not isinstance(data, Mapping):
+             raise ValueError("Only input mappings are supported.")
+         for k, v in uniq_attrs_dict.items():



More information about the arch-commits mailing list