Imported Upstream version 3.7.3
[platform/upstream/python-gobject.git] / gi / overrides / __init__.py
1 import types
2 import warnings
3 import functools
4
5 from gi import PyGIDeprecationWarning
6 from gi._gobject.constants import \
7     TYPE_NONE, \
8     TYPE_INVALID
9
10 # support overrides in different directories than our gi module
11 from pkgutil import extend_path
12 __path__ = extend_path(__path__, __name__)
13
14 registry = None
15
16
17 class _Registry(dict):
18     def __setitem__(self, key, value):
19         '''We do checks here to make sure only submodules of the override
20         module are added.  Key and value should be the same object and come
21         from the gi.override module.
22
23         We add the override to the dict as "override_module.name".  For instance
24         if we were overriding Gtk.Button you would retrive it as such:
25         registry['Gtk.Button']
26         '''
27         if not key == value:
28             raise KeyError('You have tried to modify the registry.  This should only be done by the override decorator')
29
30         try:
31             info = getattr(value, '__info__')
32         except AttributeError:
33             raise TypeError('Can not override a type %s, which is not in a gobject introspection typelib' % value.__name__)
34
35         if not value.__module__.startswith('gi.overrides'):
36             raise KeyError('You have tried to modify the registry outside of the overrides module.  This is not allowed')
37
38         g_type = info.get_g_type()
39         assert g_type != TYPE_NONE
40         if g_type != TYPE_INVALID:
41             g_type.pytype = value
42
43             # strip gi.overrides from module name
44             module = value.__module__[13:]
45             key = "%s.%s" % (module, value.__name__)
46             super(_Registry, self).__setitem__(key, value)
47
48     def register(self, override_class):
49         self[override_class] = override_class
50
51
52 class overridefunc(object):
53     '''decorator for overriding a function'''
54     def __init__(self, func):
55         if not hasattr(func, '__info__'):
56             raise TypeError("func must be an gi function")
57         from ..importer import modules
58         self.module = modules[func.__module__]._introspection_module
59
60     def __call__(self, func):
61         def wrapper(*args, **kwargs):
62             return func(*args, **kwargs)
63         wrapper.__name__ = func.__name__
64         setattr(self.module, func.__name__, wrapper)
65         return wrapper
66
67 registry = _Registry()
68
69
70 def override(type_):
71     '''Decorator for registering an override'''
72     if isinstance(type_, types.FunctionType):
73         return overridefunc(type_)
74     else:
75         registry.register(type_)
76         return type_
77
78
79 def deprecated(fn, replacement):
80     '''Decorator for marking methods and classes as deprecated'''
81     @functools.wraps(fn)
82     def wrapped(*args, **kwargs):
83         warnings.warn('%s is deprecated; use %s instead' % (fn.__name__, replacement),
84                       PyGIDeprecationWarning, stacklevel=2)
85         return fn(*args, **kwargs)
86     return wrapped