From 4d1c3e15f9b9e8a55ae6b92585c5c57923931357 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 27 Jan 2020 10:11:46 +0000 Subject: [PATCH 1/3] gdbus-codegen: Rename --glib-min-version to --glib-min-required MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it consistent with the `GLIB_MIN_REQUIRED` defines which are used for API stability/versioning in C code. It doesn’t otherwise change the behaviour of the `--glib-min-version` argument. Signed-off-by: Philip Withnall Helps: #1993 --- docs/reference/gio/gdbus-codegen.xml | 6 ++-- gio/gdbus-2.0/codegen/codegen.py | 44 +++++++++++++-------------- gio/gdbus-2.0/codegen/codegen_main.py | 42 ++++++++++++------------- gio/tests/codegen.py | 44 +++++++++++++-------------- gio/tests/gdbus-test-codegen.c | 6 ++-- gio/tests/meson.build | 16 +++++----- 6 files changed, 79 insertions(+), 79 deletions(-) diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml index 5efb3080b..9d62c3757 100644 --- a/docs/reference/gio/gdbus-codegen.xml +++ b/docs/reference/gio/gdbus-codegen.xml @@ -50,7 +50,7 @@ VALUE - VERSION + VERSION FILE FILE @@ -422,14 +422,14 @@ gdbus-codegen --c-namespace MyApp \ - VERSION + VERSION Specifies the minimum version of GLib which the code generated by gdbus-codegen can depend on. This may be used to make backwards-incompatible changes in the output or behaviour of gdbus-codegen in future, which users may opt in to - by increasing the value they pass for . + by increasing the value they pass for . If this option is not passed, the output from gdbus-codegen is guaranteed to be compatible with all versions of GLib from 2.30 upwards, as that is when gdbus-codegen was first diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py index 41481b8c2..b778bffb5 100644 --- a/gio/gdbus-2.0/codegen/codegen.py +++ b/gio/gdbus-2.0/codegen/codegen.py @@ -62,7 +62,7 @@ def generate_header_guard(header_name): class HeaderCodeGenerator: def __init__(self, ifaces, namespace, generate_objmanager, generate_autocleanup, header_name, input_files_basenames, - use_pragma, glib_min_version, outfile): + use_pragma, glib_min_required, outfile): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.generate_objmanager = generate_objmanager @@ -70,12 +70,12 @@ class HeaderCodeGenerator: self.header_guard = generate_header_guard(header_name) self.input_files_basenames = input_files_basenames self.use_pragma = use_pragma - self.glib_min_version = glib_min_version + self.glib_min_required = glib_min_required self.outfile = outfile - self.glib_min_version_is_2_64 = (glib_min_version[0] > 2 or - (glib_min_version[0] == 2 and - glib_min_version[1] >= 64)) + self.glib_min_required_is_2_64 = (glib_min_required[0] > 2 or + (glib_min_required[0] == 2 and + glib_min_required[1] >= 64)) # ---------------------------------------------------------------------------------------------------- @@ -226,7 +226,7 @@ class HeaderCodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -256,7 +256,7 @@ class HeaderCodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -629,13 +629,13 @@ class HeaderCodeGenerator: # ---------------------------------------------------------------------------------------------------- class InterfaceInfoHeaderCodeGenerator: - def __init__(self, ifaces, namespace, header_name, input_files_basenames, use_pragma, glib_min_version, outfile): + def __init__(self, ifaces, namespace, header_name, input_files_basenames, use_pragma, glib_min_required, outfile): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.header_guard = generate_header_guard(header_name) self.input_files_basenames = input_files_basenames self.use_pragma = use_pragma - self.glib_min_version = glib_min_version + self.glib_min_required = glib_min_required self.outfile = outfile # ---------------------------------------------------------------------------------------------------- @@ -683,12 +683,12 @@ class InterfaceInfoHeaderCodeGenerator: # ---------------------------------------------------------------------------------------------------- class InterfaceInfoBodyCodeGenerator: - def __init__(self, ifaces, namespace, header_name, input_files_basenames, glib_min_version, outfile): + def __init__(self, ifaces, namespace, header_name, input_files_basenames, glib_min_required, outfile): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.header_name = header_name self.input_files_basenames = input_files_basenames - self.glib_min_version = glib_min_version + self.glib_min_required = glib_min_required self.outfile = outfile # ---------------------------------------------------------------------------------------------------- @@ -916,19 +916,19 @@ class InterfaceInfoBodyCodeGenerator: class CodeGenerator: def __init__(self, ifaces, namespace, generate_objmanager, header_name, - input_files_basenames, docbook_gen, glib_min_version, outfile): + input_files_basenames, docbook_gen, glib_min_required, outfile): self.ifaces = ifaces self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) self.generate_objmanager = generate_objmanager self.header_name = header_name self.input_files_basenames = input_files_basenames self.docbook_gen = docbook_gen - self.glib_min_version = glib_min_version + self.glib_min_required = glib_min_required self.outfile = outfile - self.glib_min_version_is_2_64 = (glib_min_version[0] > 2 or - (glib_min_version[0] == 2 and - glib_min_version[1] >= 64)) + self.glib_min_required_is_2_64 = (glib_min_required[0] > 2 or + (glib_min_required[0] == 2 and + glib_min_required[1] >= 64)) # ---------------------------------------------------------------------------------------------------- @@ -1680,7 +1680,7 @@ class CodeGenerator: %(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(' * @arg_%s: Argument to pass with the method invocation.\n'%(a.name)) - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(' * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n' ' authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n' ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n' @@ -1704,7 +1704,7 @@ class CodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -1726,7 +1726,7 @@ class CodeGenerator: for a in m.in_args: self.outfile.write(',\n arg_%s'%(a.name)) self.outfile.write('),\n') - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(' call_flags,\n' ' timeout_msec,\n') else: @@ -1797,7 +1797,7 @@ class CodeGenerator: %(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(' * @arg_%s: Argument to pass with the method invocation.\n'%(a.name)) - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(' * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n' ' authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n' ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n' @@ -1824,7 +1824,7 @@ class CodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -1850,7 +1850,7 @@ class CodeGenerator: for a in m.in_args: self.outfile.write(',\n arg_%s'%(a.name)) self.outfile.write('),\n') - if self.glib_min_version_is_2_64: + if self.glib_min_required_is_2_64: self.outfile.write(' call_flags,\n' ' timeout_msec,\n') else: diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py index aecacc76d..60e1ae042 100644 --- a/gio/gdbus-2.0/codegen/codegen_main.py +++ b/gio/gdbus-2.0/codegen/codegen_main.py @@ -167,7 +167,7 @@ def codegen_main(): help='Use "pragma once" as the inclusion guard') arg_parser.add_argument('--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE', help='Add annotation (may be used several times)') - arg_parser.add_argument('--glib-min-version', metavar='VERSION', + arg_parser.add_argument('--glib-min-required', metavar='VERSION', help='Minimum version of GLib to be supported by the outputted code (default: 2.30)') group = arg_parser.add_mutually_exclusive_group() @@ -235,30 +235,30 @@ def codegen_main(): c_file = args.output header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h' - # Check the minimum GLib version. The minimum --glib-min-version is 2.30, + # Check the minimum GLib version. The minimum --glib-min-required is 2.30, # because that’s when gdbus-codegen was introduced. Support 1, 2 or 3 # component versions, but ignore the micro component if it’s present. - if args.glib_min_version: + if args.glib_min_required: try: - parts = args.glib_min_version.split('.', 3) - glib_min_version = (int(parts[0]), - int(parts[1] if len(parts) > 1 else 0)) + parts = args.glib_min_required.split('.', 3) + glib_min_required = (int(parts[0]), + int(parts[1] if len(parts) > 1 else 0)) # Ignore micro component, but still validate it: _ = int(parts[2] if len(parts) > 2 else 0) except (ValueError, IndexError): - print_error('Unrecognized --glib-min-version string ‘{}’'.format( - args.glib_min_version)) + print_error('Unrecognized --glib-min-required string ‘{}’'.format( + args.glib_min_required)) - if glib_min_version[0] < 2 or \ - (glib_min_version[0] == 2 and glib_min_version[1] < 30): - print_error('Invalid --glib-min-version string ‘{}’: minimum ' - 'version is 2.30'.format(args.glib_min_version)) + if glib_min_required[0] < 2 or \ + (glib_min_required[0] == 2 and glib_min_required[1] < 30): + print_error('Invalid --glib-min-required string ‘{}’: minimum ' + 'version is 2.30'.format(args.glib_min_required)) else: - glib_min_version = (2, 30) + glib_min_required = (2, 30) - glib_min_version_is_2_64 = (glib_min_version[0] > 2 or - (glib_min_version[0] == 2 and - glib_min_version[1] >= 64)) + glib_min_required_is_2_64 = (glib_min_required[0] > 2 or + (glib_min_required[0] == 2 and + glib_min_required[1] >= 64)) all_ifaces = [] input_files_basenames = [] @@ -266,7 +266,7 @@ def codegen_main(): with open(fname, 'rb') as f: xml_data = f.read() parsed_ifaces = parser.parse_dbus_xml(xml_data, - h_type_implies_unix_fd=glib_min_version_is_2_64) + h_type_implies_unix_fd=glib_min_required_is_2_64) all_ifaces.extend(parsed_ifaces) input_files_basenames.append(os.path.basename(fname)) @@ -290,7 +290,7 @@ def codegen_main(): header_name, input_files_basenames, args.pragma_once, - glib_min_version, + glib_min_required, outfile) gen.generate() @@ -302,7 +302,7 @@ def codegen_main(): header_name, input_files_basenames, docbook_gen, - glib_min_version, + glib_min_required, outfile) gen.generate() @@ -313,7 +313,7 @@ def codegen_main(): header_name, input_files_basenames, args.pragma_once, - glib_min_version, + glib_min_required, outfile) gen.generate() @@ -323,7 +323,7 @@ def codegen_main(): args.c_namespace, header_name, input_files_basenames, - glib_min_version, + glib_min_required, outfile) gen.generate() diff --git a/gio/tests/codegen.py b/gio/tests/codegen.py index 9d8bfadd1..bbb51117d 100644 --- a/gio/tests/codegen.py +++ b/gio/tests/codegen.py @@ -362,38 +362,38 @@ G_END_DECLS # The output should be the same. self.assertEqual(result1.out, result2.out) - def test_glib_min_version_invalid(self): - """Test running with an invalid --glib-min-version.""" + def test_glib_min_required_invalid(self): + """Test running with an invalid --glib-min-required.""" with self.assertRaises(subprocess.CalledProcessError): self.runCodegenWithInterface('', '--output', '/dev/stdout', '--body', - '--glib-min-version', 'hello mum') + '--glib-min-required', 'hello mum') - def test_glib_min_version_too_low(self): - """Test running with a --glib-min-version which is too low (and hence + def test_glib_min_required_too_low(self): + """Test running with a --glib-min-required which is too low (and hence probably a typo).""" with self.assertRaises(subprocess.CalledProcessError): self.runCodegenWithInterface('', '--output', '/dev/stdout', '--body', - '--glib-min-version', '2.6') + '--glib-min-required', '2.6') - def test_glib_min_version_major_only(self): - """Test running with a --glib-min-version which contains only a major version.""" + def test_glib_min_required_major_only(self): + """Test running with a --glib-min-required which contains only a major version.""" result = self.runCodegenWithInterface('', '--output', '/dev/stdout', '--header', - '--glib-min-version', '3') + '--glib-min-required', '3') self.assertEqual('', result.err) self.assertNotEqual('', result.out.strip()) - def test_glib_min_version_with_micro(self): - """Test running with a --glib-min-version which contains a micro version.""" + def test_glib_min_required_with_micro(self): + """Test running with a --glib-min-required which contains a micro version.""" result = self.runCodegenWithInterface('', '--output', '/dev/stdout', '--header', - '--glib-min-version', '2.46.2') + '--glib-min-required', '2.46.2') self.assertEqual('', result.err) self.assertNotEqual('', result.out.strip()) @@ -422,28 +422,28 @@ G_END_DECLS ''' - # Try without specifying --glib-min-version. + # Try without specifying --glib-min-required. result = self.runCodegenWithInterface(interface_xml, '--output', '/dev/stdout', '--header') self.assertEqual('', result.err) self.assertEqual(result.out.strip().count('GUnixFDList'), 6) - # Specify an old --glib-min-version. + # Specify an old --glib-min-required. result = self.runCodegenWithInterface(interface_xml, '--output', '/dev/stdout', '--header', - '--glib-min-version', '2.32') + '--glib-min-required', '2.32') self.assertEqual('', result.err) self.assertEqual(result.out.strip().count('GUnixFDList'), 6) - # Specify a --glib-min-version ≥ 2.64. There should be more + # Specify a --glib-min-required ≥ 2.64. There should be more # mentions of `GUnixFDList` now, since the annotation is not needed to # trigger its use. result = self.runCodegenWithInterface(interface_xml, '--output', '/dev/stdout', '--header', - '--glib-min-version', '2.64') + '--glib-min-required', '2.64') self.assertEqual('', result.err) self.assertEqual(result.out.strip().count('GUnixFDList'), 18) @@ -458,7 +458,7 @@ G_END_DECLS ''' - # Try without specifying --glib-min-version. + # Try without specifying --glib-min-required. result = self.runCodegenWithInterface(interface_xml, '--output', '/dev/stdout', '--header') @@ -466,21 +466,21 @@ G_END_DECLS self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 0) self.assertEqual(result.out.strip().count('gint timeout_msec,'), 0) - # Specify an old --glib-min-version. + # Specify an old --glib-min-required. result = self.runCodegenWithInterface(interface_xml, '--output', '/dev/stdout', '--header', - '--glib-min-version', '2.32') + '--glib-min-required', '2.32') self.assertEqual('', result.err) self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 0) self.assertEqual(result.out.strip().count('gint timeout_msec,'), 0) - # Specify a --glib-min-version ≥ 2.64. The two arguments should be + # Specify a --glib-min-required ≥ 2.64. The two arguments should be # present for both the async and sync method call functions. result = self.runCodegenWithInterface(interface_xml, '--output', '/dev/stdout', '--header', - '--glib-min-version', '2.64') + '--glib-min-required', '2.64') self.assertEqual('', result.err) self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 2) self.assertEqual(result.out.strip().count('gint timeout_msec,'), 2) diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c index 604c85c03..691506f0f 100644 --- a/gio/tests/gdbus-test-codegen.c +++ b/gio/tests/gdbus-test-codegen.c @@ -26,7 +26,7 @@ #include "gdbus-tests.h" #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64 -#include "gdbus-test-codegen-generated-min-version-2-64.h" +#include "gdbus-test-codegen-generated-min-required-2-64.h" #else #include "gdbus-test-codegen-generated.h" #endif @@ -2693,7 +2693,7 @@ handle_no_annotation_nested (FooiGenFDPassing *object, /* Test that generated code for methods includes GUnixFDList arguments * unconditionally if the method is explicitly annotated as C.UnixFD, and only * emits GUnixFDList arguments when there's merely an 'h' parameter if - * --glib-min-version=2.64 or greater. + * --glib-min-required=2.64 or greater. */ static void test_unix_fd_list (void) @@ -2707,7 +2707,7 @@ test_unix_fd_list (void) /* This one is not annotated; even though it's got an in and out 'h' * parameter, for backwards compatibility we cannot emit GUnixFDList - * arguments unless --glib-min-version >= 2.64 was used. + * arguments unless --glib-min-required >= 2.64 was used. */ iface.handle_no_annotation = handle_no_annotation; diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 6345eab7f..2264539b0 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -231,17 +231,17 @@ if host_machine.system() != 'windows' '--generate-docbook', 'gdbus-test-codegen-generated-doc', annotate_args, '@INPUT@']) - # Generate gdbus-test-codegen-generated-min-version-2-64.{c,h} - gdbus_test_codegen_generated_min_version_2_64 = custom_target('gdbus-test-codegen-generated-min-version-2-64', + # Generate gdbus-test-codegen-generated-min-required-2-64.{c,h} + gdbus_test_codegen_generated_min_required_2_64 = custom_target('gdbus-test-codegen-generated-min-required-2-64', input : ['test-codegen.xml'], - output : ['gdbus-test-codegen-generated-min-version-2-64.h', - 'gdbus-test-codegen-generated-min-version-2-64.c'], + output : ['gdbus-test-codegen-generated-min-required-2-64.h', + 'gdbus-test-codegen-generated-min-required-2-64.c'], depend_files : gdbus_codegen_built_files, command : [python, gdbus_codegen, - '--glib-min-version', '2.64', + '--glib-min-required', '2.64', '--interface-prefix', 'org.project.', '--output-directory', '@OUTDIR@', - '--generate-c-code', 'gdbus-test-codegen-generated-min-version-2-64', + '--generate-c-code', 'gdbus-test-codegen-generated-min-required-2-64', '--c-generate-object-manager', '--c-generate-autocleanup', 'all', '--c-namespace', 'Foo_iGen', @@ -318,9 +318,9 @@ if host_machine.system() != 'windows' 'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36', '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_36'], }, - 'gdbus-test-codegen-min-version-2-64' : { + 'gdbus-test-codegen-min-required-2-64' : { 'source' : 'gdbus-test-codegen.c', - 'extra_sources' : [extra_sources, gdbus_test_codegen_generated_min_version_2_64, gdbus_test_codegen_generated_interface_info], + 'extra_sources' : [extra_sources, gdbus_test_codegen_generated_min_required_2_64, gdbus_test_codegen_generated_interface_info], 'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_64'], }, 'gapplication' : {'extra_sources' : extra_sources}, From 9734e4854ebeaee684d566daa97cb518c4488b0e Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 27 Jan 2020 10:36:03 +0000 Subject: [PATCH 2/3] gdbus-codegen: Add --glib-max-allowed argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This complements the `--glib-min-required` argument, just like the `GLIB_MIN_REQUIRED` and `GLIB_MAX_ALLOWED` preprocessor defines which control access to APIs in C. Currently, it doesn’t affect code generation at all. When we next change code generation, we will need to gate any new API usage on this argument. Signed-off-by: Philip Withnall Fixes: #1993 --- docs/reference/gio/gdbus-codegen.xml | 22 ++++++++++++ gio/gdbus-2.0/codegen/codegen_main.py | 24 +++++++++++++ gio/gdbus-2.0/codegen/config.py.in | 2 ++ gio/gdbus-2.0/codegen/meson.build | 2 ++ gio/tests/codegen.py | 52 ++++++++++++++++++++++++++- 5 files changed, 101 insertions(+), 1 deletion(-) diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml index 9d62c3757..9687681fd 100644 --- a/docs/reference/gio/gdbus-codegen.xml +++ b/docs/reference/gio/gdbus-codegen.xml @@ -51,6 +51,7 @@ VERSION + VERSION FILE FILE @@ -460,6 +461,27 @@ gdbus-codegen --c-namespace MyApp \ + + VERSION + + + Specifies the maximum version of GLib which the code generated by + gdbus-codegen can depend on. This may be used to + ensure that code generated by gdbus-codegen is + compilable with specific older versions of GLib that your software has + to support. + + + The version number must be of the form + MAJOR.MINOR.MICRO, + where all parts are integers. MINOR and + MICRO are optional. The version number must + be greater than or equal to that passed to . + It defaults to the version of GLib which provides this gdbus-codegen. + + + + diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py index 60e1ae042..c938640e7 100644 --- a/gio/gdbus-2.0/codegen/codegen_main.py +++ b/gio/gdbus-2.0/codegen/codegen_main.py @@ -169,6 +169,8 @@ def codegen_main(): help='Add annotation (may be used several times)') arg_parser.add_argument('--glib-min-required', metavar='VERSION', help='Minimum version of GLib to be supported by the outputted code (default: 2.30)') + arg_parser.add_argument('--glib-max-allowed', metavar='VERSION', + help='Maximum version of GLib to be used by the outputted code (default: current GLib version)') group = arg_parser.add_mutually_exclusive_group() group.add_argument('--generate-c-code', metavar='OUTFILES', @@ -256,6 +258,28 @@ def codegen_main(): else: glib_min_required = (2, 30) + # And the maximum GLib version. + if args.glib_max_allowed: + try: + parts = args.glib_max_allowed.split('.', 3) + glib_max_allowed = (int(parts[0]), + int(parts[1] if len(parts) > 1 else 0)) + # Ignore micro component, but still validate it: + _ = int(parts[2] if len(parts) > 2 else 0) + except (ValueError, IndexError): + print_error('Unrecognized --glib-max-allowed string ‘{}’'.format( + args.glib_max_allowed)) + else: + glib_max_allowed = (config.MAJOR_VERSION, config.MINOR_VERSION) + + # Round --glib-max-allowed up to the next stable release. + glib_max_allowed = \ + (glib_max_allowed[0], glib_max_allowed[1] + (glib_max_allowed[1] % 2)) + + if glib_max_allowed < glib_min_required: + print_error('Invalid versions: --glib-min-required ({}) must be ' + 'less than or equal to --glib-max-allowed ({})'.format(glib_min_required, glib_max_allowed)) + glib_min_required_is_2_64 = (glib_min_required[0] > 2 or (glib_min_required[0] == 2 and glib_min_required[1] >= 64)) diff --git a/gio/gdbus-2.0/codegen/config.py.in b/gio/gdbus-2.0/codegen/config.py.in index a91178a95..4e6df5a09 100644 --- a/gio/gdbus-2.0/codegen/config.py.in +++ b/gio/gdbus-2.0/codegen/config.py.in @@ -20,3 +20,5 @@ # Author: David Zeuthen VERSION = "@VERSION@" +MAJOR_VERSION = @MAJOR_VERSION@ +MINOR_VERSION = @MINOR_VERSION@ diff --git a/gio/gdbus-2.0/codegen/meson.build b/gio/gdbus-2.0/codegen/meson.build index 121e9e6bb..ff5edb977 100644 --- a/gio/gdbus-2.0/codegen/meson.build +++ b/gio/gdbus-2.0/codegen/meson.build @@ -10,6 +10,8 @@ gdbus_codegen_files = [ gdbus_codegen_conf = configuration_data() gdbus_codegen_conf.set('VERSION', glib_version) +gdbus_codegen_conf.set('MAJOR_VERSION', major_version) +gdbus_codegen_conf.set('MINOR_VERSION', minor_version) gdbus_codegen_conf.set('PYTHON', python_name) gdbus_codegen_conf.set('DATADIR', glib_datadir) diff --git a/gio/tests/codegen.py b/gio/tests/codegen.py index bbb51117d..51de0ede4 100644 --- a/gio/tests/codegen.py +++ b/gio/tests/codegen.py @@ -384,7 +384,8 @@ G_END_DECLS result = self.runCodegenWithInterface('', '--output', '/dev/stdout', '--header', - '--glib-min-required', '3') + '--glib-min-required', '3', + '--glib-max-allowed', '3.2') self.assertEqual('', result.err) self.assertNotEqual('', result.out.strip()) @@ -397,6 +398,55 @@ G_END_DECLS self.assertEqual('', result.err) self.assertNotEqual('', result.out.strip()) + def test_glib_max_allowed_too_low(self): + """Test running with a --glib-max-allowed which is too low (and hence + probably a typo).""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegenWithInterface('', + '--output', '/dev/stdout', + '--body', + '--glib-max-allowed', '2.6') + + def test_glib_max_allowed_major_only(self): + """Test running with a --glib-max-allowed which contains only a major version.""" + result = self.runCodegenWithInterface('', + '--output', '/dev/stdout', + '--header', + '--glib-max-allowed', '3') + self.assertEqual('', result.err) + self.assertNotEqual('', result.out.strip()) + + def test_glib_max_allowed_with_micro(self): + """Test running with a --glib-max-allowed which contains a micro version.""" + result = self.runCodegenWithInterface('', + '--output', '/dev/stdout', + '--header', + '--glib-max-allowed', '2.46.2') + self.assertEqual('', result.err) + self.assertNotEqual('', result.out.strip()) + + def test_glib_max_allowed_unstable(self): + """Test running with a --glib-max-allowed which is unstable. It should + be rounded up to the next stable version number, and hence should not + end up less than --glib-min-required.""" + result = self.runCodegenWithInterface('', + '--output', '/dev/stdout', + '--header', + '--glib-max-allowed', '2.63', + '--glib-min-required', '2.64') + self.assertEqual('', result.err) + self.assertNotEqual('', result.out.strip()) + + def test_glib_max_allowed_less_than_min_required(self): + """Test running with a --glib-max-allowed which is less than + --glib-min-required.""" + with self.assertRaises(subprocess.CalledProcessError): + self.runCodegenWithInterface('', + '--output', '/dev/stdout', + '--body', + '--glib-max-allowed', '2.62', + '--glib-min-required', '2.64') + def test_unix_fd_types_and_annotations(self): """Test an interface with `h` arguments, no annotation, and GLib < 2.64. From 087b9829f486f54f174943c677a1580aed9d7b27 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 31 Jan 2020 12:23:22 +0000 Subject: [PATCH 3/3] gdbus-codegen: Tidy up version comparisons Python tuple comparisons actually do what we want for comparing major and minor versions, so tidy things up by using that. This introduces no functional changes. Signed-off-by: Philip Withnall --- gio/gdbus-2.0/codegen/codegen.py | 24 ++++++++---------------- gio/gdbus-2.0/codegen/codegen_main.py | 9 ++------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py index b778bffb5..d71299ebe 100644 --- a/gio/gdbus-2.0/codegen/codegen.py +++ b/gio/gdbus-2.0/codegen/codegen.py @@ -73,10 +73,6 @@ class HeaderCodeGenerator: self.glib_min_required = glib_min_required self.outfile = outfile - self.glib_min_required_is_2_64 = (glib_min_required[0] > 2 or - (glib_min_required[0] == 2 and - glib_min_required[1] >= 64)) - # ---------------------------------------------------------------------------------------------------- def generate_header_preamble(self): @@ -226,7 +222,7 @@ class HeaderCodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -256,7 +252,7 @@ class HeaderCodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -926,10 +922,6 @@ class CodeGenerator: self.glib_min_required = glib_min_required self.outfile = outfile - self.glib_min_required_is_2_64 = (glib_min_required[0] > 2 or - (glib_min_required[0] == 2 and - glib_min_required[1] >= 64)) - # ---------------------------------------------------------------------------------------------------- def generate_body_preamble(self): @@ -1680,7 +1672,7 @@ class CodeGenerator: %(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(' * @arg_%s: Argument to pass with the method invocation.\n'%(a.name)) - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(' * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n' ' authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n' ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n' @@ -1704,7 +1696,7 @@ class CodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -1726,7 +1718,7 @@ class CodeGenerator: for a in m.in_args: self.outfile.write(',\n arg_%s'%(a.name)) self.outfile.write('),\n') - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(' call_flags,\n' ' timeout_msec,\n') else: @@ -1797,7 +1789,7 @@ class CodeGenerator: %(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(' * @arg_%s: Argument to pass with the method invocation.\n'%(a.name)) - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(' * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n' ' authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n' ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n' @@ -1824,7 +1816,7 @@ class CodeGenerator: ' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name)) for a in m.in_args: self.outfile.write(',\n %sarg_%s'%(a.ctype_in, a.name)) - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(',\n GDBusCallFlags call_flags' ',\n gint timeout_msec') if m.unix_fd: @@ -1850,7 +1842,7 @@ class CodeGenerator: for a in m.in_args: self.outfile.write(',\n arg_%s'%(a.name)) self.outfile.write('),\n') - if self.glib_min_required_is_2_64: + if self.glib_min_required >= (2, 64): self.outfile.write(' call_flags,\n' ' timeout_msec,\n') else: diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py index c938640e7..75d97e3c7 100644 --- a/gio/gdbus-2.0/codegen/codegen_main.py +++ b/gio/gdbus-2.0/codegen/codegen_main.py @@ -251,8 +251,7 @@ def codegen_main(): print_error('Unrecognized --glib-min-required string ‘{}’'.format( args.glib_min_required)) - if glib_min_required[0] < 2 or \ - (glib_min_required[0] == 2 and glib_min_required[1] < 30): + if glib_min_required < (2, 30): print_error('Invalid --glib-min-required string ‘{}’: minimum ' 'version is 2.30'.format(args.glib_min_required)) else: @@ -280,17 +279,13 @@ def codegen_main(): print_error('Invalid versions: --glib-min-required ({}) must be ' 'less than or equal to --glib-max-allowed ({})'.format(glib_min_required, glib_max_allowed)) - glib_min_required_is_2_64 = (glib_min_required[0] > 2 or - (glib_min_required[0] == 2 and - glib_min_required[1] >= 64)) - all_ifaces = [] input_files_basenames = [] for fname in sorted(args.files + args.xml_files): with open(fname, 'rb') as f: xml_data = f.read() parsed_ifaces = parser.parse_dbus_xml(xml_data, - h_type_implies_unix_fd=glib_min_required_is_2_64) + h_type_implies_unix_fd=(glib_min_required >= (2, 64))) all_ifaces.extend(parsed_ifaces) input_files_basenames.append(os.path.basename(fname))