mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-11-17 16:08:21 +01:00
gdbus-codegen: Add an extension system which allows hooking codegen
The extension points are chosen by what libdex needs to generate future based method calls.
This commit is contained in:
committed by
Philip Withnall
parent
07ba38449e
commit
4405fe5fc8
@@ -47,6 +47,7 @@ SYNOPSIS
|
|||||||
| [--annotate *ELEMENT* *KEY* *VALUE*]…
|
| [--annotate *ELEMENT* *KEY* *VALUE*]…
|
||||||
| [--glib-min-required *VERSION*]
|
| [--glib-min-required *VERSION*]
|
||||||
| [--glib-max-allowed *VERSION*]
|
| [--glib-max-allowed *VERSION*]
|
||||||
|
| [--extension-path *EXTENSION_PATH*]
|
||||||
| *FILE*…
|
| *FILE*…
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@@ -392,6 +393,20 @@ The following options are supported:
|
|||||||
greater than or equal to that passed to ``--glib-min-required``.
|
greater than or equal to that passed to ``--glib-min-required``.
|
||||||
It defaults to the version of GLib which provides this ``gdbus-codegen``.
|
It defaults to the version of GLib which provides this ``gdbus-codegen``.
|
||||||
|
|
||||||
|
``--extension-path`` *EXTENSION_PATH*
|
||||||
|
|
||||||
|
Used to load an extension to the codegen. The *EXTENSION_PATH* is a path to
|
||||||
|
a Python file that will be loaded as a module. The extension needs to define
|
||||||
|
at least the function ``def init(args, options)`` where ``args`` is a
|
||||||
|
``argparse.Namespace`` and ``options`` is a dict containing the key
|
||||||
|
``version``.
|
||||||
|
|
||||||
|
All other API the extension can use are internal and thus unstable, but effort
|
||||||
|
is made to increase the ``version`` field when those internals change. If you
|
||||||
|
want to use this mechanism, please get in touch by
|
||||||
|
`filing an issue <https://gitlab.gnome.org/GNOME/glib/-/issues>`_. with your
|
||||||
|
use case.
|
||||||
|
|
||||||
SUPPORTED D-BUS ANNOTATIONS
|
SUPPORTED D-BUS ANNOTATIONS
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,54 @@ LICENSE_STR = """/*
|
|||||||
# flake8: noqa: E501
|
# flake8: noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
def extensionpoint(func):
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
# ensures same signature
|
||||||
|
func(*args, **kwargs)
|
||||||
|
if not self._ext:
|
||||||
|
return
|
||||||
|
method = getattr(self._ext, func.__name__, None)
|
||||||
|
if not method:
|
||||||
|
return
|
||||||
|
method(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class ExtensionGenerator:
|
||||||
|
def __init__(self, ext, generator):
|
||||||
|
if self.extending != generator.__class__.__name__:
|
||||||
|
raise Exception("Trying to extend wrong class")
|
||||||
|
self._ext = None
|
||||||
|
klass = getattr(ext, self.extending, None)
|
||||||
|
if klass:
|
||||||
|
self._ext = klass(generator)
|
||||||
|
|
||||||
|
|
||||||
|
class ExtensionHeaderCodeGenerator(ExtensionGenerator):
|
||||||
|
extending = "HeaderCodeGenerator"
|
||||||
|
|
||||||
|
@extensionpoint
|
||||||
|
def generate_includes():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@extensionpoint
|
||||||
|
def declare_types():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExtensionCodeGenerator(ExtensionGenerator):
|
||||||
|
extending = "CodeGenerator"
|
||||||
|
|
||||||
|
@extensionpoint
|
||||||
|
def generate_body_preamble():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@extensionpoint
|
||||||
|
def generate():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def generate_namespace(namespace):
|
def generate_namespace(namespace):
|
||||||
ns = namespace
|
ns = namespace
|
||||||
if len(namespace) > 0:
|
if len(namespace) > 0:
|
||||||
@@ -84,6 +132,7 @@ class HeaderCodeGenerator:
|
|||||||
symbol_decorator,
|
symbol_decorator,
|
||||||
symbol_decorator_header,
|
symbol_decorator_header,
|
||||||
outfile,
|
outfile,
|
||||||
|
ext,
|
||||||
):
|
):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
||||||
@@ -96,6 +145,7 @@ class HeaderCodeGenerator:
|
|||||||
self.symbol_decorator = symbol_decorator
|
self.symbol_decorator = symbol_decorator
|
||||||
self.symbol_decorator_header = symbol_decorator_header
|
self.symbol_decorator_header = symbol_decorator_header
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
self.ext = ExtensionHeaderCodeGenerator(ext, self)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -116,6 +166,7 @@ class HeaderCodeGenerator:
|
|||||||
|
|
||||||
self.outfile.write("\n")
|
self.outfile.write("\n")
|
||||||
self.outfile.write("#include <gio/gio.h>\n")
|
self.outfile.write("#include <gio/gio.h>\n")
|
||||||
|
self.ext.generate_includes()
|
||||||
self.outfile.write("\n")
|
self.outfile.write("\n")
|
||||||
self.outfile.write("G_BEGIN_DECLS\n")
|
self.outfile.write("G_BEGIN_DECLS\n")
|
||||||
self.outfile.write("\n")
|
self.outfile.write("\n")
|
||||||
@@ -360,6 +411,7 @@ class HeaderCodeGenerator:
|
|||||||
" GError **error);\n"
|
" GError **error);\n"
|
||||||
)
|
)
|
||||||
self.outfile.write("\n")
|
self.outfile.write("\n")
|
||||||
|
|
||||||
self.outfile.write("\n")
|
self.outfile.write("\n")
|
||||||
|
|
||||||
# Then the property accessor declarations
|
# Then the property accessor declarations
|
||||||
@@ -1014,6 +1066,7 @@ class HeaderCodeGenerator:
|
|||||||
def generate(self):
|
def generate(self):
|
||||||
self.generate_header_preamble()
|
self.generate_header_preamble()
|
||||||
self.declare_types()
|
self.declare_types()
|
||||||
|
self.ext.declare_types()
|
||||||
self.generate_header_postamble()
|
self.generate_header_postamble()
|
||||||
|
|
||||||
|
|
||||||
@@ -1458,6 +1511,7 @@ class CodeGenerator:
|
|||||||
glib_min_required,
|
glib_min_required,
|
||||||
symbol_decoration_define,
|
symbol_decoration_define,
|
||||||
outfile,
|
outfile,
|
||||||
|
ext,
|
||||||
):
|
):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
||||||
@@ -1469,6 +1523,7 @@ class CodeGenerator:
|
|||||||
self.symbol_decoration_define = symbol_decoration_define
|
self.symbol_decoration_define = symbol_decoration_define
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
self.marshallers = set()
|
self.marshallers = set()
|
||||||
|
self.ext = ExtensionCodeGenerator(ext, self)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -5478,6 +5533,7 @@ class CodeGenerator:
|
|||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.generate_body_preamble()
|
self.generate_body_preamble()
|
||||||
|
self.ext.generate_body_preamble()
|
||||||
for i in self.ifaces:
|
for i in self.ifaces:
|
||||||
self.generate_generic_marshallers(i)
|
self.generate_generic_marshallers(i)
|
||||||
for i in self.ifaces:
|
for i in self.ifaces:
|
||||||
@@ -5496,3 +5552,4 @@ class CodeGenerator:
|
|||||||
if self.generate_objmanager:
|
if self.generate_objmanager:
|
||||||
self.generate_object()
|
self.generate_object()
|
||||||
self.generate_object_manager_client()
|
self.generate_object_manager_client()
|
||||||
|
self.ext.generate()
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import importlib.util
|
||||||
|
import traceback
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from . import config
|
from . import config
|
||||||
@@ -38,6 +40,16 @@ from . import codegen_rst
|
|||||||
from .utils import print_error, print_warning
|
from .utils import print_error, print_warning
|
||||||
|
|
||||||
|
|
||||||
|
def import_from_path(module_name, file_path):
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
||||||
|
if not spec:
|
||||||
|
raise Exception("Not a Python file")
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
sys.modules[module_name] = module
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
def find_arg(arg_list, arg_name):
|
def find_arg(arg_list, arg_name):
|
||||||
for a in arg_list:
|
for a in arg_list:
|
||||||
if a.name == arg_name:
|
if a.name == arg_name:
|
||||||
@@ -274,6 +286,12 @@ def codegen_main():
|
|||||||
help="Additional define required for decorator specified by "
|
help="Additional define required for decorator specified by "
|
||||||
"--symbol-decorator",
|
"--symbol-decorator",
|
||||||
)
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--extension-path",
|
||||||
|
metavar="EXTENSION_PATH",
|
||||||
|
default="",
|
||||||
|
help="Path to a gdbus-codegen Python extension file (unstable API)",
|
||||||
|
)
|
||||||
|
|
||||||
group = arg_parser.add_mutually_exclusive_group()
|
group = arg_parser.add_mutually_exclusive_group()
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
@@ -305,6 +323,20 @@ def codegen_main():
|
|||||||
|
|
||||||
args = arg_parser.parse_args()
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
codegen_ext = {}
|
||||||
|
if args.extension_path:
|
||||||
|
try:
|
||||||
|
codegen_ext = import_from_path("GDBusCodegenExt", args.extension_path)
|
||||||
|
codegen_ext.init(
|
||||||
|
args,
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
print_warning(traceback.format_exc())
|
||||||
|
print_error("Loading extension ‘{}’ failed".format(args.extension_path))
|
||||||
|
|
||||||
if len(args.xml_files) > 0:
|
if len(args.xml_files) > 0:
|
||||||
print_warning(
|
print_warning(
|
||||||
'The "--xml-files" option is deprecated; use positional arguments instead'
|
'The "--xml-files" option is deprecated; use positional arguments instead'
|
||||||
@@ -479,6 +511,7 @@ def codegen_main():
|
|||||||
args.symbol_decorator,
|
args.symbol_decorator,
|
||||||
args.symbol_decorator_header,
|
args.symbol_decorator_header,
|
||||||
outfile,
|
outfile,
|
||||||
|
codegen_ext,
|
||||||
)
|
)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
@@ -494,6 +527,7 @@ def codegen_main():
|
|||||||
glib_min_required,
|
glib_min_required,
|
||||||
args.symbol_decorator_define,
|
args.symbol_decorator_define,
|
||||||
outfile,
|
outfile,
|
||||||
|
codegen_ext,
|
||||||
)
|
)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user