summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Tojnar <jtojnar@gmail.com>2023-03-10 15:02:02 +0100
committerJan Tojnar <jtojnar@gmail.com>2023-03-10 16:40:34 +0100
commit1e7467b4a8b538a48b785b05bb161b2548990e2a (patch)
tree85ac52ab6ad2d2d04dd244cc296d2aac6c16a0aa
parent6aa724d47142f272410046ecf74704b0c2898b6e (diff)
downloadpygobject-wip/jtojnar/gio-generic-list.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.py33
-rw-r--r--tests/test_properties.py3
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):