diff --git a/gst-env.py b/gst-env.py index 7b7d3ae7f7..c64042d92b 100755 --- a/gst-env.py +++ b/gst-env.py @@ -386,6 +386,7 @@ def get_subprocess_env(options, gst_version): presets = set() encoding_targets = set() python_dirs = setup_gdb(options) + overrides_dirs = set() if '--installed' in subprocess.check_output(meson + ['introspect', '-h']).decode(): installed_s = subprocess.check_output(meson + ['introspect', options.builddir, '--installed']) for path, installpath in json.loads(installed_s.decode()).items(): @@ -406,7 +407,10 @@ def get_subprocess_env(options, gst_version): if 'site-packages' in installpath_parts: install_subpath = os.path.join(*installpath_parts[installpath_parts.index('site-packages') + 1:]) if path.endswith(install_subpath): - python_dirs.add(path[:len (install_subpath) * -1]) + if os.path.commonprefix(["gi/overrides", install_subpath]): + overrides_dirs.add(os.path.dirname(path)) + else: + python_dirs.add(path[:len (install_subpath) * -1]) if path.endswith('.prs'): presets.add(os.path.dirname(path)) @@ -432,11 +436,18 @@ def get_subprocess_env(options, gst_version): for python_dir in sorted(python_dirs): prepend_env_var(env, 'PYTHONPATH', python_dir, options.sysroot) + for python_dir in sorted(overrides_dirs): + prepend_env_var(env, '_GI_OVERRIDES_PATH', python_dir, options.sysroot) + mesonpath = os.path.join(SCRIPTDIR, "meson") if os.path.join(mesonpath): # Add meson/ into PYTHONPATH if we are using a local meson prepend_env_var(env, 'PYTHONPATH', mesonpath, options.sysroot) + # Ensure that gst-python/gi is used first + prepend_env_var(env, "PYTHONPATH", os.path.join(SCRIPTDIR, 'subprojects', 'gst-python'), + options.sysroot) + # For devhelp books if 'XDG_DATA_DIRS' not in env or not env['XDG_DATA_DIRS']: # Preserve default paths when empty diff --git a/meson.build b/meson.build index 1458acc2fb..c23724c5e5 100644 --- a/meson.build +++ b/meson.build @@ -368,14 +368,12 @@ endforeach message('Building subprojects: ' + ', '.join(subprojects_names)) -subdir('tests') - setenv = find_program('gst-env.py') - devenv_cmd = [setenv, '--builddir=@0@'.format(meson.build_root()), '--gstbuilddir=@0@'.format(meson.current_build_dir()), '--srcdir=@0@'.format(meson.source_root())] +subdir('tests') if meson.has_exe_wrapper() and build_machine.system() == 'linux' and host_machine.system() == 'windows' # FIXME: Ideally we could get the wrapper directly from meson devenv_cmd += ['--wine', host_machine.cpu_family() == 'x86_64' ? 'wine64' : 'wine32'] diff --git a/subprojects/gst-python/gi/__init__.py b/subprojects/gst-python/gi/__init__.py new file mode 100644 index 0000000000..4f356a6ede --- /dev/null +++ b/subprojects/gst-python/gi/__init__.py @@ -0,0 +1,45 @@ +import gi +import os +import sys +import imp +from pathlib import Path + +# Remove this dummy module the python path and +# try to import the actual gi module +sys.path.remove(str(Path(__file__).parents[1])) +del sys.modules["gi"] +import gi + + +class GstOverrideImport: + def find_module(self, fullname, path=None, target=None): + if fullname.startswith('gi.overrides'): + fp = None + try: + fp, _, _ = imp.find_module(fullname.split( + '.')[-1], os.environ.get('_GI_OVERRIDES_PATH', '').split(os.pathsep),) + except ImportError: + return None + finally: + if fp: + fp.close() + return self + return None + + def load_module(self, name): + if name in sys.modules: + return sys.modules[name] + + fp, pathname, description = imp.find_module(name.split( + '.')[-1], os.environ.get('_GI_OVERRIDES_PATH', '').split(os.pathsep),) + + try: + module = imp.load_module(name, fp, pathname, description) + finally: + if fp: + fp.close() + sys.modules[name] = module + return module + + +sys.meta_path.insert(0, GstOverrideImport()) diff --git a/tests/meson.build b/tests/meson.build index 6884250f76..3159b9cdb1 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -2,3 +2,4 @@ if get_option('tests').disabled() subdir_done() endif subdir('static-plugins') +subdir('python') \ No newline at end of file diff --git a/tests/python/meson.build b/tests/python/meson.build new file mode 100644 index 0000000000..b391044b7e --- /dev/null +++ b/tests/python/meson.build @@ -0,0 +1,19 @@ +gst_python = subproject('gst-python', required: false) +gir = find_program('g-ir-scanner', required : get_option('introspection')) +if not gst_python.found() or not gir.found() + message('Not running python devenv tests: gst_python: @0@ gir: @1@'.format(gst_python.found(), gir.found())) + subdir_done() +endif + +root_rel = '../..' +python = import('python').find_installation() + +if run_command(python, '-c', 'import gi').returncode() != 0 + message('PyGObject not found, not running PyGObject tests') + subdir_done() +endif + +test('python-overrides-devenv', setenv, args: ['--builddir=@0@'.format(meson.build_root()), + '--gstbuilddir=@0@'.format(meson.current_build_dir() / '..' / '..'), + '--srcdir=@0@'.format(meson.source_root()), + meson.current_source_dir() / 'python-devenv-overrides.py']) \ No newline at end of file diff --git a/tests/python/python-devenv-overrides.py b/tests/python/python-devenv-overrides.py new file mode 100755 index 0000000000..0c099118ea --- /dev/null +++ b/tests/python/python-devenv-overrides.py @@ -0,0 +1,20 @@ +#!/usr/bin/python3 +import unittest +from pathlib import Path +from unittest import TestCase +from gi.repository import Gst + + +class TestBin(TestCase): + def test_overrides(self): + from gi.overrides import Gst + self.assertEqual(Path(Gst.__file__), Path(__file__).parents[2] / "subprojects/gst-python/gi/overrides/Gst.py") + + def simple_functional_test(self): + Gst.init(None) + self.assertEqual(Gst.ElementFactory.make("bin", None).sinkpads, []) + self.assertEqual(float(Gst.Fraction(1, 2)), 0.5) + + +if __name__ == "__main__": + unittest.main()