|
|
@ -1,4 +1,4 @@
|
|
|
|
From eb791e7cca0998bc75e0b3f7e8ecf2672c96d7f8 Mon Sep 17 00:00:00 2001
|
|
|
|
From 1212d1cd3d4b47294770408a7abd18bc4c578a64 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Ray Strode <rstrode@redhat.com>
|
|
|
|
From: Ray Strode <rstrode@redhat.com>
|
|
|
|
Date: Wed, 10 Jun 2020 18:04:07 -0400
|
|
|
|
Date: Wed, 10 Jun 2020 18:04:07 -0400
|
|
|
|
Subject: [PATCH] IntrospectionModule: handle two threads loading type at same
|
|
|
|
Subject: [PATCH] IntrospectionModule: handle two threads loading type at same
|
|
|
@ -16,17 +16,93 @@ on each others toes.
|
|
|
|
gi/module.py | 110 +++++++++++++++++++++++++++------------------------
|
|
|
|
gi/module.py | 110 +++++++++++++++++++++++++++------------------------
|
|
|
|
1 file changed, 58 insertions(+), 52 deletions(-)
|
|
|
|
1 file changed, 58 insertions(+), 52 deletions(-)
|
|
|
|
|
|
|
|
|
|
|
|
--- a/gi/module.py 2020-06-10 18:09:19.292409072 -0400
|
|
|
|
diff --git a/gi/module.py b/gi/module.py
|
|
|
|
+++ b/gi/module.py 2020-06-10 18:11:24.727045466 -0400
|
|
|
|
index f9e26bc2..93b8e6a3 100644
|
|
|
|
@@ -24,6 +24,7 @@ from __future__ import absolute_import
|
|
|
|
--- a/gi/module.py
|
|
|
|
|
|
|
|
+++ b/gi/module.py
|
|
|
|
|
|
|
|
@@ -1,53 +1,54 @@
|
|
|
|
|
|
|
|
# -*- Mode: Python; py-indent-offset: 4 -*-
|
|
|
|
|
|
|
|
# vim: tabstop=4 shiftwidth=4 expandtab
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# Copyright (C) 2007-2009 Johan Dahlin <johan@gnome.org>
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# module.py: dynamic module for introspected libraries.
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# This library is free software; you can redistribute it and/or
|
|
|
|
|
|
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
|
|
|
# License as published by the Free Software Foundation; either
|
|
|
|
|
|
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# This library is distributed in the hope that it will be useful,
|
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
|
|
|
# Lesser General Public License for more details.
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
|
|
|
# License along with this library; if not, write to the Free Software
|
|
|
|
|
|
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
|
|
|
|
|
|
|
# USA
|
|
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import importlib
|
|
|
|
import importlib
|
|
|
|
+from threading import Lock
|
|
|
|
+from threading import Lock
|
|
|
|
|
|
|
|
|
|
|
|
_have_py3 = (sys.version_info[0] >= 3)
|
|
|
|
import gi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ._gi import \
|
|
|
|
|
|
|
|
Repository, \
|
|
|
|
|
|
|
|
FunctionInfo, \
|
|
|
|
|
|
|
|
RegisteredTypeInfo, \
|
|
|
|
|
|
|
|
EnumInfo, \
|
|
|
|
|
|
|
|
ObjectInfo, \
|
|
|
|
|
|
|
|
InterfaceInfo, \
|
|
|
|
|
|
|
|
ConstantInfo, \
|
|
|
|
|
|
|
|
StructInfo, \
|
|
|
|
|
|
|
|
UnionInfo, \
|
|
|
|
|
|
|
|
CallbackInfo, \
|
|
|
|
|
|
|
|
Struct, \
|
|
|
|
|
|
|
|
Boxed, \
|
|
|
|
|
|
|
|
CCallback, \
|
|
|
|
|
|
|
|
enum_add, \
|
|
|
|
|
|
|
|
enum_register_new_gtype_and_add, \
|
|
|
|
|
|
|
|
flags_add, \
|
|
|
|
|
|
|
|
flags_register_new_gtype_and_add, \
|
|
|
|
|
|
|
|
GInterface
|
|
|
|
|
|
|
|
from .types import \
|
|
|
|
|
|
|
|
GObjectMeta, \
|
|
|
|
|
|
|
|
StructMeta
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ._constants import \
|
|
|
|
|
|
|
|
TYPE_NONE, \
|
|
|
|
|
|
|
|
TYPE_BOXED, \
|
|
|
|
|
|
|
|
TYPE_POINTER, \
|
|
|
|
|
|
|
|
@@ -90,152 +91,157 @@ def get_interfaces_for_object(object_info):
|
|
|
|
|
|
|
|
namespace = interface_info.get_namespace()
|
|
|
|
|
|
|
|
name = interface_info.get_name()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module = importlib.import_module('gi.repository.' + namespace)
|
|
|
|
|
|
|
|
interfaces.append(getattr(module, name))
|
|
|
|
|
|
|
|
return interfaces
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class IntrospectionModule(object):
|
|
|
|
|
|
|
|
"""An object which wraps an introspection typelib.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This wrapping creates a python module like representation of the typelib
|
|
|
|
|
|
|
|
using gi repository as a foundation. Accessing attributes of the module
|
|
|
|
|
|
|
|
will dynamically pull them in and create wrappers for the members.
|
|
|
|
|
|
|
|
These members are then cached on this introspection module.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, namespace, version=None):
|
|
|
|
|
|
|
|
"""Might raise gi._gi.RepositoryError"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
repository.require(namespace, version)
|
|
|
|
|
|
|
|
self._namespace = namespace
|
|
|
|
|
|
|
|
self._version = version
|
|
|
|
|
|
|
|
self.__name__ = 'gi.repository.' + namespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
path = repository.get_typelib_path(self._namespace)
|
|
|
|
|
|
|
|
self.__path__ = [path]
|
|
|
|
|
|
|
|
|
|
|
|
@@ -131,6 +132,8 @@ class IntrospectionModule(object):
|
|
|
|
|
|
|
|
if self._version is None:
|
|
|
|
if self._version is None:
|
|
|
|
self._version = repository.get_version(self._namespace)
|
|
|
|
self._version = repository.get_version(self._namespace)
|
|
|
|
|
|
|
|
|
|
|
@ -35,13 +111,12 @@ on each others toes.
|
|
|
|
def __getattr__(self, name):
|
|
|
|
def __getattr__(self, name):
|
|
|
|
info = repository.find_by_name(self._namespace, name)
|
|
|
|
info = repository.find_by_name(self._namespace, name)
|
|
|
|
if not info:
|
|
|
|
if not info:
|
|
|
|
@@ -139,39 +142,40 @@ class IntrospectionModule(object):
|
|
|
|
raise AttributeError("%r object has no attribute %r" % (
|
|
|
|
|
|
|
|
self.__name__, name))
|
|
|
|
|
|
|
|
|
|
|
|
if isinstance(info, EnumInfo):
|
|
|
|
if isinstance(info, EnumInfo):
|
|
|
|
g_type = info.get_g_type()
|
|
|
|
g_type = info.get_g_type()
|
|
|
|
- wrapper = g_type.pytype
|
|
|
|
- wrapper = g_type.pytype
|
|
|
|
+ with self._lock:
|
|
|
|
|
|
|
|
+ wrapper = g_type.pytype
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- if wrapper is None:
|
|
|
|
- if wrapper is None:
|
|
|
|
- if info.is_flags():
|
|
|
|
- if info.is_flags():
|
|
|
@ -53,6 +128,9 @@ on each others toes.
|
|
|
|
- else:
|
|
|
|
- else:
|
|
|
|
- if g_type.is_a(TYPE_ENUM):
|
|
|
|
- if g_type.is_a(TYPE_ENUM):
|
|
|
|
- wrapper = enum_add(g_type)
|
|
|
|
- wrapper = enum_add(g_type)
|
|
|
|
|
|
|
|
+ with self._lock:
|
|
|
|
|
|
|
|
+ wrapper = g_type.pytype
|
|
|
|
|
|
|
|
+
|
|
|
|
+ if wrapper is None:
|
|
|
|
+ if wrapper is None:
|
|
|
|
+ if info.is_flags():
|
|
|
|
+ if info.is_flags():
|
|
|
|
+ if g_type.is_a(TYPE_FLAGS):
|
|
|
|
+ if g_type.is_a(TYPE_FLAGS):
|
|
|
@ -70,7 +148,7 @@ on each others toes.
|
|
|
|
- # Don't use upper() here to avoid locale specific
|
|
|
|
- # Don't use upper() here to avoid locale specific
|
|
|
|
- # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
|
|
|
|
- # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
|
|
|
|
- # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
|
|
|
|
- # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
|
|
|
|
- ascii_upper_trans = maketrans(
|
|
|
|
- ascii_upper_trans = ''.maketrans(
|
|
|
|
- 'abcdefgjhijklmnopqrstuvwxyz',
|
|
|
|
- 'abcdefgjhijklmnopqrstuvwxyz',
|
|
|
|
- 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
|
|
|
|
- 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
|
|
|
|
- for value_info in info.get_values():
|
|
|
|
- for value_info in info.get_values():
|
|
|
@ -78,6 +156,9 @@ on each others toes.
|
|
|
|
- setattr(wrapper, value_name, wrapper(value_info.get_value()))
|
|
|
|
- setattr(wrapper, value_name, wrapper(value_info.get_value()))
|
|
|
|
- for method_info in info.get_methods():
|
|
|
|
- for method_info in info.get_methods():
|
|
|
|
- setattr(wrapper, method_info.__name__, method_info)
|
|
|
|
- setattr(wrapper, method_info.__name__, method_info)
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
- if g_type != TYPE_NONE:
|
|
|
|
|
|
|
|
- g_type.pytype = wrapper
|
|
|
|
+ if g_type.is_a(TYPE_ENUM):
|
|
|
|
+ if g_type.is_a(TYPE_ENUM):
|
|
|
|
+ wrapper = enum_add(g_type)
|
|
|
|
+ wrapper = enum_add(g_type)
|
|
|
|
+ else:
|
|
|
|
+ else:
|
|
|
@ -90,7 +171,7 @@ on each others toes.
|
|
|
|
+ # Don't use upper() here to avoid locale specific
|
|
|
|
+ # Don't use upper() here to avoid locale specific
|
|
|
|
+ # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
|
|
|
|
+ # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
|
|
|
|
+ # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
|
|
|
|
+ # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
|
|
|
|
+ ascii_upper_trans = maketrans(
|
|
|
|
+ ascii_upper_trans = ''.maketrans(
|
|
|
|
+ 'abcdefgjhijklmnopqrstuvwxyz',
|
|
|
|
+ 'abcdefgjhijklmnopqrstuvwxyz',
|
|
|
|
+ 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
|
|
|
|
+ 'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
|
|
|
|
+ for value_info in info.get_values():
|
|
|
|
+ for value_info in info.get_values():
|
|
|
@ -98,15 +179,36 @@ on each others toes.
|
|
|
|
+ setattr(wrapper, value_name, wrapper(value_info.get_value()))
|
|
|
|
+ setattr(wrapper, value_name, wrapper(value_info.get_value()))
|
|
|
|
+ for method_info in info.get_methods():
|
|
|
|
+ for method_info in info.get_methods():
|
|
|
|
+ setattr(wrapper, method_info.__name__, method_info)
|
|
|
|
+ setattr(wrapper, method_info.__name__, method_info)
|
|
|
|
|
|
|
|
+
|
|
|
|
- if g_type != TYPE_NONE:
|
|
|
|
|
|
|
|
- g_type.pytype = wrapper
|
|
|
|
|
|
|
|
+ if g_type != TYPE_NONE:
|
|
|
|
+ if g_type != TYPE_NONE:
|
|
|
|
+ g_type.pytype = wrapper
|
|
|
|
+ g_type.pytype = wrapper
|
|
|
|
|
|
|
|
|
|
|
|
elif isinstance(info, RegisteredTypeInfo):
|
|
|
|
elif isinstance(info, RegisteredTypeInfo):
|
|
|
|
g_type = info.get_g_type()
|
|
|
|
g_type = info.get_g_type()
|
|
|
|
@@ -202,27 +206,28 @@ class IntrospectionModule(object):
|
|
|
|
|
|
|
|
|
|
|
|
# Create a wrapper.
|
|
|
|
|
|
|
|
if isinstance(info, ObjectInfo):
|
|
|
|
|
|
|
|
parent = get_parent_for_object(info)
|
|
|
|
|
|
|
|
interfaces = tuple(interface for interface in get_interfaces_for_object(info)
|
|
|
|
|
|
|
|
if not issubclass(parent, interface))
|
|
|
|
|
|
|
|
bases = (parent,) + interfaces
|
|
|
|
|
|
|
|
metaclass = GObjectMeta
|
|
|
|
|
|
|
|
elif isinstance(info, CallbackInfo):
|
|
|
|
|
|
|
|
bases = (CCallback,)
|
|
|
|
|
|
|
|
metaclass = GObjectMeta
|
|
|
|
|
|
|
|
elif isinstance(info, InterfaceInfo):
|
|
|
|
|
|
|
|
bases = (GInterface,)
|
|
|
|
|
|
|
|
metaclass = GObjectMeta
|
|
|
|
|
|
|
|
elif isinstance(info, (StructInfo, UnionInfo)):
|
|
|
|
|
|
|
|
if g_type.is_a(TYPE_BOXED):
|
|
|
|
|
|
|
|
bases = (Boxed,)
|
|
|
|
|
|
|
|
elif (g_type.is_a(TYPE_POINTER) or
|
|
|
|
|
|
|
|
g_type == TYPE_NONE or
|
|
|
|
|
|
|
|
g_type.fundamental == g_type):
|
|
|
|
|
|
|
|
bases = (Struct,)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
raise TypeError("unable to create a wrapper for %s.%s" % (info.get_namespace(), info.get_name()))
|
|
|
|
|
|
|
|
metaclass = StructMeta
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
raise NotImplementedError(info)
|
|
|
|
raise NotImplementedError(info)
|
|
|
|
|
|
|
|
|
|
|
@ -156,3 +258,33 @@ on each others toes.
|
|
|
|
|
|
|
|
|
|
|
|
elif isinstance(info, FunctionInfo):
|
|
|
|
elif isinstance(info, FunctionInfo):
|
|
|
|
wrapper = info
|
|
|
|
wrapper = info
|
|
|
|
|
|
|
|
elif isinstance(info, ConstantInfo):
|
|
|
|
|
|
|
|
wrapper = info.get_value()
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
raise NotImplementedError(info)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Cache the newly created wrapper which will then be
|
|
|
|
|
|
|
|
# available directly on this introspection module instead of being
|
|
|
|
|
|
|
|
# lazily constructed through the __getattr__ we are currently in.
|
|
|
|
|
|
|
|
self.__dict__[name] = wrapper
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
|
|
|
path = repository.get_typelib_path(self._namespace)
|
|
|
|
|
|
|
|
return "<IntrospectionModule %r from %r>" % (self._namespace, path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __dir__(self):
|
|
|
|
|
|
|
|
# Python's default dir() is just dir(self.__class__) + self.__dict__.keys()
|
|
|
|
|
|
|
|
result = set(dir(self.__class__))
|
|
|
|
|
|
|
|
result.update(self.__dict__.keys())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# update *set* because some repository attributes have already been
|
|
|
|
|
|
|
|
# wrapped by __getattr__() and included in self.__dict__; but skip
|
|
|
|
|
|
|
|
# Callback types, as these are not real objects which we can actually
|
|
|
|
|
|
|
|
# get
|
|
|
|
|
|
|
|
namespace_infos = repository.get_infos(self._namespace)
|
|
|
|
|
|
|
|
result.update(info.get_name() for info in namespace_infos if
|
|
|
|
|
|
|
|
not isinstance(info, CallbackInfo))
|
|
|
|
|
|
|
|
--
|
|
|
|
|
|
|
|
2.31.1
|
|
|
|
|
|
|
|
|
|
|
|