# Copyright (c) 2013-2014 LOGILAB S.A. (Paris, FRANCE) # Copyright (c) 2014 Google, Inc. # Copyright (c) 2014 Cole Robinson # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa # Copyright (c) 2015-2016 Ceridwen # Copyright (c) 2015 David Shea # Copyright (c) 2016 Jakub Wilk # Copyright (c) 2016 Giuseppe Scrivano # Copyright (c) 2018 Christoph Reiter # Copyright (c) 2019 Philipp Hörist # Copyright (c) 2020-2021 hippo91 # Copyright (c) 2021 Pierre Sassoulas # Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com> # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com> # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE """Astroid hooks for the Python 2 GObject introspection bindings. Helps with understanding everything imported from 'gi.repository' """ # pylint:disable=import-error,import-outside-toplevel import inspect import itertools import re import sys import warnings from astroid import nodes from astroid.builder import AstroidBuilder from astroid.exceptions import AstroidBuildingError from astroid.manager import AstroidManager _inspected_modules = {} _identifier_re = r"^[A-Za-z_]\w*$" _special_methods = frozenset( { "__lt__", "__le__", "__eq__", "__ne__", "__ge__", "__gt__", "__iter__", "__getitem__", "__setitem__", "__delitem__", "__len__", "__bool__", "__nonzero__", "__next__", "__str__", "__len__", "__contains__", "__enter__", "__exit__", "__repr__", "__getattr__", "__setattr__", "__delattr__", "__del__", "__hash__", } ) def _gi_build_stub(parent): """ Inspect the passed module recursively and build stubs for functions, classes, etc. """ classes = {} functions = {} constants = {} methods = {} for name in dir(parent): if name.startswith("__") and name not in _special_methods: continue # Check if this is a valid name in python if not re.match(_identifier_re, name): continue try: obj = getattr(parent, name) except AttributeError: continue if inspect.isclass(obj): classes[name] = obj elif inspect.isfunction(obj) or inspect.isbuiltin(obj): functions[name] = obj elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj): methods[name] = obj elif ( str(obj).startswith(", ) # Only accept function calls with two constant arguments if len(node.args) != 2: return False if not all(isinstance(arg, nodes.Const) for arg in node.args): return False func = node.func if isinstance(func, nodes.Attribute): if func.attrname != "require_version": return False if isinstance(func.expr, nodes.Name) and func.expr.name == "gi": return True return False if isinstance(func, nodes.Name): return func.name == "require_version" return False def _register_require_version(node): # Load the gi.require_version locally try: import gi gi.require_version(node.args[0].value, node.args[1].value) except Exception: # pylint:disable=broad-except pass return node AstroidManager().register_failed_import_hook(_import_gi_module) AstroidManager().register_transform( nodes.Call, _register_require_version, _looks_like_require_version )