mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
python: Fix using overrides when not building PyGObject
Since 547570cd79
we do not always build
PyGObject and our development environment is broken when trying to use
GStreamer python when built against system PyGObject with the following
error importing Gst in there:
```
12345678** (gst-plugin-scanner:710617): CRITICAL **: 11:45:02.343: can't find gi.repository.Gst
Traceback (most recent call last):
File "/usr/lib/python3.9/site-packages/gi/repository/__init__.py", line 23, in <module>
from ..importer import DynamicImporter
File "/usr/lib64/python3.9/site-packages/gi/importer.py", line 33, in <module>
from .overrides import load_overrides
ImportError: cannot import name 'load_overrides' from 'gi.overrides' (/var/home/thiblahute/devel/gstreamer/gstreamer/subprojects/gst-editing-services/bindings/python/gi/overrides/__init__.py)
Factory Details:
```
The approach to fixing it is to implement override `gi` in
`gst-python/gi/` which we add to `PYTHONPATH`) and in there reset the
`gi` module to the right place and we get overrides from paths from
`_GI_OVERRIDES_PATH` we set in `gst-env.py` which points to all the
overrides that will be installed.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1155>
This commit is contained in:
parent
ba79339d56
commit
1babccfe50
6 changed files with 98 additions and 4 deletions
11
gst-env.py
11
gst-env.py
|
@ -386,6 +386,7 @@ def get_subprocess_env(options, gst_version):
|
||||||
presets = set()
|
presets = set()
|
||||||
encoding_targets = set()
|
encoding_targets = set()
|
||||||
python_dirs = setup_gdb(options)
|
python_dirs = setup_gdb(options)
|
||||||
|
overrides_dirs = set()
|
||||||
if '--installed' in subprocess.check_output(meson + ['introspect', '-h']).decode():
|
if '--installed' in subprocess.check_output(meson + ['introspect', '-h']).decode():
|
||||||
installed_s = subprocess.check_output(meson + ['introspect', options.builddir, '--installed'])
|
installed_s = subprocess.check_output(meson + ['introspect', options.builddir, '--installed'])
|
||||||
for path, installpath in json.loads(installed_s.decode()).items():
|
for path, installpath in json.loads(installed_s.decode()).items():
|
||||||
|
@ -406,6 +407,9 @@ def get_subprocess_env(options, gst_version):
|
||||||
if 'site-packages' in installpath_parts:
|
if 'site-packages' in installpath_parts:
|
||||||
install_subpath = os.path.join(*installpath_parts[installpath_parts.index('site-packages') + 1:])
|
install_subpath = os.path.join(*installpath_parts[installpath_parts.index('site-packages') + 1:])
|
||||||
if path.endswith(install_subpath):
|
if path.endswith(install_subpath):
|
||||||
|
if os.path.commonprefix(["gi/overrides", install_subpath]):
|
||||||
|
overrides_dirs.add(os.path.dirname(path))
|
||||||
|
else:
|
||||||
python_dirs.add(path[:len (install_subpath) * -1])
|
python_dirs.add(path[:len (install_subpath) * -1])
|
||||||
|
|
||||||
if path.endswith('.prs'):
|
if path.endswith('.prs'):
|
||||||
|
@ -432,11 +436,18 @@ def get_subprocess_env(options, gst_version):
|
||||||
for python_dir in sorted(python_dirs):
|
for python_dir in sorted(python_dirs):
|
||||||
prepend_env_var(env, 'PYTHONPATH', python_dir, options.sysroot)
|
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")
|
mesonpath = os.path.join(SCRIPTDIR, "meson")
|
||||||
if os.path.join(mesonpath):
|
if os.path.join(mesonpath):
|
||||||
# Add meson/ into PYTHONPATH if we are using a local meson
|
# Add meson/ into PYTHONPATH if we are using a local meson
|
||||||
prepend_env_var(env, 'PYTHONPATH', mesonpath, options.sysroot)
|
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
|
# For devhelp books
|
||||||
if 'XDG_DATA_DIRS' not in env or not env['XDG_DATA_DIRS']:
|
if 'XDG_DATA_DIRS' not in env or not env['XDG_DATA_DIRS']:
|
||||||
# Preserve default paths when empty
|
# Preserve default paths when empty
|
||||||
|
|
|
@ -368,14 +368,12 @@ endforeach
|
||||||
|
|
||||||
message('Building subprojects: ' + ', '.join(subprojects_names))
|
message('Building subprojects: ' + ', '.join(subprojects_names))
|
||||||
|
|
||||||
subdir('tests')
|
|
||||||
|
|
||||||
setenv = find_program('gst-env.py')
|
setenv = find_program('gst-env.py')
|
||||||
|
|
||||||
devenv_cmd = [setenv, '--builddir=@0@'.format(meson.build_root()),
|
devenv_cmd = [setenv, '--builddir=@0@'.format(meson.build_root()),
|
||||||
'--gstbuilddir=@0@'.format(meson.current_build_dir()),
|
'--gstbuilddir=@0@'.format(meson.current_build_dir()),
|
||||||
'--srcdir=@0@'.format(meson.source_root())]
|
'--srcdir=@0@'.format(meson.source_root())]
|
||||||
|
|
||||||
|
subdir('tests')
|
||||||
if meson.has_exe_wrapper() and build_machine.system() == 'linux' and host_machine.system() == 'windows'
|
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
|
# FIXME: Ideally we could get the wrapper directly from meson
|
||||||
devenv_cmd += ['--wine', host_machine.cpu_family() == 'x86_64' ? 'wine64' : 'wine32']
|
devenv_cmd += ['--wine', host_machine.cpu_family() == 'x86_64' ? 'wine64' : 'wine32']
|
||||||
|
|
45
subprojects/gst-python/gi/__init__.py
Normal file
45
subprojects/gst-python/gi/__init__.py
Normal file
|
@ -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())
|
|
@ -2,3 +2,4 @@ if get_option('tests').disabled()
|
||||||
subdir_done()
|
subdir_done()
|
||||||
endif
|
endif
|
||||||
subdir('static-plugins')
|
subdir('static-plugins')
|
||||||
|
subdir('python')
|
19
tests/python/meson.build
Normal file
19
tests/python/meson.build
Normal file
|
@ -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'])
|
20
tests/python/python-devenv-overrides.py
Executable file
20
tests/python/python-devenv-overrides.py
Executable file
|
@ -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()
|
Loading…
Reference in a new issue