diff options
author | Jan Tojnar <jtojnar@gmail.com> | 2023-03-10 15:02:02 +0100 |
---|---|---|
committer | Jan Tojnar <jtojnar@gmail.com> | 2023-03-10 16:40:34 +0100 |
commit | 1e7467b4a8b538a48b785b05bb161b2548990e2a (patch) | |
tree | 85ac52ab6ad2d2d04dd244cc296d2aac6c16a0aa | |
parent | 6aa724d47142f272410046ecf74704b0c2898b6e (diff) | |
download | pygobject-1e7467b4a8b538a48b785b05bb161b2548990e2a.tar.gz |
Support instances of Generic types in propertyhelperwip/jtojnar/gio-generic-list
Subscribing a subclass of `Generic[...]` (e.g. `Gio.ListStore[Gio.File]`)
will turn it into instance of `typing._GenericAlias`.
That is not an instance of `type`, nor a subclass of the subscribed class.
To allow passing instantiated generic types as `type` argument of `Property`,
we need to extract the generic type, or property will fail with `Unsupported type` error.
Unfortunately, `typing` module only provides helper for that since Python 3.8
so we need to create our own `get_origin` that looks into internal state for 3.7.
-rw-r--r-- | gi/_propertyhelper.py | 33 | ||||
-rw-r--r-- | tests/test_properties.py | 3 |
2 files changed, 30 insertions, 6 deletions
diff --git a/gi/_propertyhelper.py b/gi/_propertyhelper.py index def34b22..69357553 100644 --- a/gi/_propertyhelper.py +++ b/gi/_propertyhelper.py @@ -26,6 +26,21 @@ from ._constants import \ TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \ TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV, TYPE_VARIANT + +from typing import Optional +try: + # Only available in Python 3.8 or later. + from typing import get_origin +except ImportError: + from typing import _GenericAlias + + def get_origin(type_: object) -> Optional[type]: + """Get the unsubscripted version of a type.""" + if isinstance(type_, _GenericAlias): + return type_.__origin__ + return None + + G_MAXFLOAT = _gi.G_MAXFLOAT G_MAXDOUBLE = _gi.G_MAXDOUBLE G_MININT = _gi.G_MININT @@ -249,12 +264,18 @@ class Property(object): def _type_from_python(self, type_): if type_ in self._type_from_pytype_lookup: return self._type_from_pytype_lookup[type_] - elif (isinstance(type_, type) and - issubclass(type_, (_gi.GObject, - _gi.GEnum, - _gi.GFlags, - _gi.GBoxed, - _gi.GInterface))): + + # Support instances of generic types such as Gio.ListStore[Gio.File] + origin = get_origin(type_) + if origin is not None: + type_ = origin + + if (isinstance(type_, type) and + issubclass(type_, (_gi.GObject, + _gi.GEnum, + _gi.GFlags, + _gi.GBoxed, + _gi.GInterface))): return type_.__gtype__ elif type_ in (TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG, diff --git a/tests/test_properties.py b/tests/test_properties.py index ec5df0ca..0092b7ff 100644 --- a/tests/test_properties.py +++ b/tests/test_properties.py @@ -746,6 +746,9 @@ class TestProperty(unittest.TestCase): PropertyObjectSubclass(obj=ObjectSubclass()) + def test_generic_instance_property(self): + GObject.Property(type=Gio.ListStore[Gio.File]) + def test_property_subclass(self): # test for #470718 class A(GObject.GObject): |