[neon/forks/sip6/Neon/release] debian: Backport upstream patch to fix handling of composite classes.

Dmitry Shachnev null at kde.org
Sat Feb 4 02:04:46 GMT 2023


Git commit 37b2bd4bb8d249ddae6db1c8ca804fc7036a8f2c by Dmitry Shachnev.
Committed on 02/02/2023 at 09:08.
Pushed by carlosdem into branch 'Neon/release'.

Backport upstream patch to fix handling of composite classes.

Closes: #1030188.

M  +7    -0    debian/changelog
A  +471  -0    debian/patches/composite_classes.diff
M  +1    -0    debian/patches/series

https://invent.kde.org/neon/forks/sip6/commit/37b2bd4bb8d249ddae6db1c8ca804fc7036a8f2c

diff --git a/debian/changelog b/debian/changelog
index 2153ecd..53eceb6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+sip6 (6.7.6+dfsg-2) UNRELEASED; urgency=medium
+
+  * Backport upstream patch to fix handling of composite classes
+    (closes: #1030188).
+
+ -- Dmitry Shachnev <mitya57 at debian.org>  Thu, 02 Feb 2023 13:07:19 +0400
+
 sip6 (6.7.6+dfsg-1) unstable; urgency=medium
 
   * New upstream release.
diff --git a/debian/patches/composite_classes.diff b/debian/patches/composite_classes.diff
new file mode 100644
index 0000000..f28f527
--- /dev/null
+++ b/debian/patches/composite_classes.diff
@@ -0,0 +1,471 @@
+From: Phil Thompson <phil at riverbankcomputing.com>
+Date: Tue, 31 Jan 2023 16:59:37 +0000
+Subject: Refactored the handling of composite classes so that they are
+ populated properly.
+
+Origin: upstream, https://riverbankcomputing.com/hg/sip/rev/0afab92347b6
+---
+ code_generator/gencode.c                    | 22 ++-----
+ code_generator/py2c.c                       | 10 +---
+ code_generator/sip.h                        |  7 +--
+ sipbuild/bindings.py                        |  4 +-
+ sipbuild/generator/outputs/pyi.py           |  4 +-
+ sipbuild/generator/parser/parser_manager.py | 90 +++++++++++++----------------
+ sipbuild/generator/parser/rules.py          | 29 ++++------
+ sipbuild/generator/specification.py         | 11 ++--
+ 8 files changed, 67 insertions(+), 110 deletions(-)
+
+diff --git a/code_generator/gencode.c b/code_generator/gencode.c
+index 9fc917c..ad83fa1 100644
+--- a/code_generator/gencode.c
++++ b/code_generator/gencode.c
+@@ -1,7 +1,7 @@
+ /*
+  * The code generator module for SIP.
+  *
+- * Copyright (c) 2022 Riverbank Computing Limited <info at riverbankcomputing.com>
++ * Copyright (c) 2023 Riverbank Computing Limited <info at riverbankcomputing.com>
+  *
+  * This file is part of SIP.
+  *
+@@ -342,7 +342,7 @@ stringList *generateCode(sipSpec *pt, char *codeDir, const char *srcSuffix,
+     if (srcSuffix == NULL)
+         srcSuffix = (generating_c ? ".c" : ".cpp");
+ 
+-    if (isComposite(pt->module))
++    if (pt->is_composite)
+     {
+         if (generateCompositeCpp(pt, codeDir, &generated, py_debug) < 0)
+             return NULL;
+@@ -1098,10 +1098,9 @@ static int generateCompositeCpp(sipSpec *pt, const char *codeDir,
+         );
+ 
+     for (mld = pt->module->allimports; mld != NULL; mld = mld->next)
+-        if (mld->module->container == pt->module)
+-            prcode(fp,
++        prcode(fp,
+ "    sip_import_component_module(sipModuleDict, \"%s\");\n"
+-                , mld->module->fullname->text);
++            , mld->module->fullname->text);
+ 
+     prcode(fp,
+ "\n"
+@@ -1229,8 +1228,7 @@ static const char *generateCpp(sipSpec *pt, moduleDef *mod,
+             );
+ 
+     /* Define the names. */
+-    if (mod->container == NULL)
+-        generateNameCache(pt, fp);
++    generateNameCache(pt, fp);
+ 
+     /* Generate the C++ code blocks. */
+     generateCppCodeBlock(mod->cppcode, fp);
+@@ -2047,15 +2045,7 @@ static const char *generateCpp(sipSpec *pt, moduleDef *mod,
+             , mname);
+ 
+     /* Generate the Python module initialisation function. */
+-
+-    if (mod->container == pt->module)
+-        prcode(fp,
+-"\n"
+-"PyObject *sip_init_%s()\n"
+-"{\n"
+-            , mname);
+-    else
+-        generateModInitStart(pt->module, generating_c, fp);
++    generateModInitStart(pt->module, generating_c, fp);
+ 
+     /* Generate the global functions. */
+ 
+diff --git a/code_generator/py2c.c b/code_generator/py2c.c
+index 2e6b3f3..fc78fd8 100644
+--- a/code_generator/py2c.c
++++ b/code_generator/py2c.c
+@@ -2,7 +2,7 @@
+  * The transitional conversion from the output of the Python-based parser to
+  * that required by the rest of the C-based code generator.
+  *
+- * Copyright (c) 2022 Riverbank Computing Limited <info at riverbankcomputing.com>
++ * Copyright (c) 2023 Riverbank Computing Limited <info at riverbankcomputing.com>
+  *
+  * This file is part of SIP.
+  *
+@@ -417,6 +417,7 @@ sipSpec *py2c(PyObject *spec, const char *encoding)
+     pt->exptypehintcode = codeblock_list_attr(spec, "exported_type_hint_code",
+             encoding);
+     pt->genc = bool_attr(spec, "c_bindings");
++    pt->is_composite = bool_attr(spec, "is_composite");
+     pt->plugins = str_list_attr(spec, "plugins", encoding);
+     pt->nrvirthandlers = int_attr(spec, "nr_virtual_handlers");
+     pt->qobject_cd = class_attr(pt, spec, "pyqt_qobject", encoding);
+@@ -1654,12 +1655,6 @@ static moduleDef *module(sipSpec *pt, PyObject *obj, const char *encoding)
+     if (bool_attr(obj, "has_delayed_dtors"))
+         setHasDelayedDtors(value);
+ 
+-    if (bool_attr(obj, "is_composite"))
+-    {
+-        setIsComposite(value);
+-        value->modflags &= ~MOD_SUPER_INIT_MASK;
+-    }
+-
+     if (bool_attr(obj, "use_arg_names"))
+         setUseArgNames(value);
+ 
+@@ -1699,7 +1694,6 @@ static moduleDef *module(sipSpec *pt, PyObject *obj, const char *encoding)
+     value->next_key = int_attr(obj, "next_key");
+     value->license = license_attr(obj, "license", encoding);
+     value->proxies = class_list_attr(pt, obj, "proxies", encoding);
+-    value->container = module_attr(pt, obj, "composite", encoding);
+     value->used = ifacefilelist_attr(pt, obj, "used", encoding);
+     value->imports = modulelist_attr(pt, obj, "imports", encoding);
+     value->allimports = modulelist_attr(pt, obj, "all_imports", encoding);
+diff --git a/code_generator/sip.h b/code_generator/sip.h
+index 23b3f49..cc427b0 100644
+--- a/code_generator/sip.h
++++ b/code_generator/sip.h
+@@ -1,7 +1,7 @@
+ /*
+  * The main header file for SIP.
+  *
+- * Copyright (c) 2022 Riverbank Computing Limited <info at riverbankcomputing.com>
++ * Copyright (c) 2023 Riverbank Computing Limited <info at riverbankcomputing.com>
+  *
+  * This file is part of SIP.
+  *
+@@ -72,7 +72,6 @@
+ 
+ #define MOD_HAS_DELAYED_DTORS   0x0001  /* It has a class with a delayed dtor. */
+ #define MOD_IS_UNUSED           0x0002  /* This flag is unused. */
+-#define MOD_IS_COMPOSITE        0x0004  /* It is a composite module. */
+ #define MOD_IS_TRANSFORMED      0x0008  /* It's types have been transformed. */
+ #define MOD_USE_ARG_NAMES       0x0010  /* Use real argument names. */
+ #define MOD_USE_LIMITED_API     0x0020  /* Use the limited API. */
+@@ -85,8 +84,6 @@
+ 
+ #define hasDelayedDtors(m)  ((m)->modflags & MOD_HAS_DELAYED_DTORS)
+ #define setHasDelayedDtors(m)   ((m)->modflags |= MOD_HAS_DELAYED_DTORS)
+-#define isComposite(m)      ((m)->modflags & MOD_IS_COMPOSITE)
+-#define setIsComposite(m)   ((m)->modflags |= MOD_IS_COMPOSITE)
+ #define setIsTransformed(m) ((m)->modflags |= MOD_IS_TRANSFORMED)
+ #define isTransformed(m)    ((m)->modflags & MOD_IS_TRANSFORMED)
+ #define setUseArgNames(m)   ((m)->modflags |= MOD_USE_ARG_NAMES)
+@@ -954,7 +951,6 @@ typedef struct _moduleDef {
+     int next_key;                       /* The next key to allocate. */
+     licenseDef *license;                /* The software license. */
+     struct _classDef *proxies;          /* The list of proxy classes. */
+-    struct _moduleDef *container;       /* The container module, if any. */
+     struct _ifaceFileList *used;        /* Interface files used. */
+     struct _moduleListDef *allimports;  /* The list of all imports. */
+     struct _moduleListDef *imports;     /* The list of direct imports. */
+@@ -1274,6 +1270,7 @@ typedef struct {
+     codeBlockList *exptypehintcode;     /* Exported type hint code. */
+     classDef *qobject_cd;               /* QObject class, NULL if none. */
+     int genc;                           /* Set if we are generating C code. */
++    int is_composite;                   /* Set if the main module is composite. */
+     struct _stringList *plugins;        /* The list of plugins. */
+     struct _extractDef *extracts;       /* The list of extracts. */
+ } sipSpec;
+diff --git a/sipbuild/bindings.py b/sipbuild/bindings.py
+index a2346c7..29758bd 100644
+--- a/sipbuild/bindings.py
++++ b/sipbuild/bindings.py
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2022, Riverbank Computing Limited
++# Copyright (c) 2023, Riverbank Computing Limited
+ # All rights reserved.
+ #
+ # This copy of SIP is licensed for use under the terms of the SIP License
+@@ -175,7 +175,7 @@ class Bindings(Configurable):
+ 
+         module = spec.module
+ 
+-        uses_limited_api = module.use_limited_api or module.is_composite
++        uses_limited_api = module.use_limited_api or spec.is_composite
+ 
+         # The details of things that will have been generated.  Note that we
+         # don't include anything for .api files or generic extracts as the
+diff --git a/sipbuild/generator/outputs/pyi.py b/sipbuild/generator/outputs/pyi.py
+index b554366..0bf2972 100644
+--- a/sipbuild/generator/outputs/pyi.py
++++ b/sipbuild/generator/outputs/pyi.py
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2022, Riverbank Computing Limited
++# Copyright (c) 2023, Riverbank Computing Limited
+ # All rights reserved.
+ #
+ # This copy of SIP is licensed for use under the terms of the SIP License
+@@ -49,7 +49,7 @@ f'''# The PEP 484 type hints stub file for the {module.py_name} module.
+ 
+ ''')
+ 
+-        if module.is_composite:
++        if spec.is_composite:
+             _composite_module(pf, spec, module)
+         else:
+             _module(pf, spec, module)
+diff --git a/sipbuild/generator/parser/parser_manager.py b/sipbuild/generator/parser/parser_manager.py
+index 6608f75..b09504d 100644
+--- a/sipbuild/generator/parser/parser_manager.py
++++ b/sipbuild/generator/parser/parser_manager.py
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2022, Riverbank Computing Limited
++# Copyright (c) 2023, Riverbank Computing Limited
+ # All rights reserved.
+ #
+ # This copy of SIP is licensed for use under the terms of the SIP License
+@@ -87,7 +87,6 @@ class ParserManager:
+         self.c_bindings = None
+         self.code_block = None
+         self.module_state = None
+-        self.module_states = []
+         self.paren_depth = 0
+         self.parsing_template = False
+         self.parsing_virtual = False
+@@ -1205,14 +1204,9 @@ class ParserManager:
+         sip_file, raw_sip_file, input, lineno, lexpos, module_state = self._file_stack.pop()
+ 
+         if module_state is None:
++            self._import_module(self._sip_file)
+             module_state = self.module_state
+ 
+-            # The current file was %Included so create a new Module and
+-            # ModuleState as if it had been %Imported.
+-            module = Module()
+-            self.modules.append(module)
+-            self.module_state = ModuleState(module, self._sip_file, self)
+-
+         self._file_stack.append(
+                 (sip_file, raw_sip_file, input, lineno, lexpos, module_state))
+ 
+@@ -1459,9 +1453,7 @@ class ParserManager:
+         code will be generated for.
+         """
+ 
+-        module = self.module_state.module
+-
+-        return module is self.spec.module or module.composite is not None
++        return self.module_state.module is self.spec.module
+ 
+     def instantiate_class_template(self, p, symbol, fq_cpp_name, template,
+             py_name, no_type_name, docstring):
+@@ -1503,7 +1495,7 @@ class ParserManager:
+         raw_sip_file = sip_file
+         sip_file = os.path.abspath(sip_file)
+ 
+-        self.module_state = ModuleState(self.spec.module, sip_file, self)
++        self.module_state = ModuleState(self.spec.module, sip_file)
+ 
+         try:
+             self._parser.parse(self._read(sip_file, raw_sip_file),
+@@ -1637,47 +1629,17 @@ class ParserManager:
+                         "'{0}' is being read recursively".format(sip_file))
+                 return
+ 
+-        if new_module:
+-            importing_from = self.module_state.module
+-
+-            # Create a new module if it has not already been defined.
+-            for module_state in self.module_states:
+-                if module_state.sip_file == sip_file:
+-                    module = module_state.module
+-                    break
+-            else:
+-                module = Module()
+-                self.modules.append(module)
+-
+-                module.default_exception = self.module_state.module.default_exception
+-                old_module_state = self.module_state
+-                self.module_state = ModuleState(module, sip_file, self)
+-
+-                # Get the configuration of the new module.
+-                mod_tags, mod_disabled = get_bindings_configuration(
+-                        self.spec.abi_version[0], sip_file, self._include_dirs)
+-
+-                for tag in mod_tags:
+-                    if tag not in self.tags:
+-                        self.tags.append(tag)
+-
+-                for feature in mod_disabled:
+-                    if feature not in self._disabled_features:
+-                        self._disabled_features.append(feature)
++        # Ignore the file if we have already read it.
++        if sip_file in self._all_sip_files:
++            return
+ 
+-            # Add the new import unless it has already been imported.
+-            if module not in importing_from.imports:
+-                importing_from.imports.insert(0, module)
++        if new_module:
++            old_module_state = self.module_state
++            self._import_module(sip_file)
+         else:
+             # This means that the file was %Included rather than %Imported.
+             old_module_state = None
+ 
+-        # Ignore the file if we have already read it. This replicates the
+-        # behaviour of the old parser but shouldn't be required for a well
+-        # specified project.
+-        if sip_file in self._all_sip_files:
+-            return
+-
+         # Save the state of the current .sip file.
+         self._file_stack.append(
+                 (self._sip_file, self.raw_sip_file, self._input,
+@@ -2116,6 +2078,34 @@ class ParserManager:
+         # call_super_init defaults to False if it wasn't specified.
+         module.call_super_init = bool(module_state.call_super_init)
+ 
++    def _import_module(self, sip_file):
++        """ Create a new Module object and corresponding ModuleState object for
++        a .sip file and make it current.
++        """
++
++        importing_from = self.module_state.module
++
++        module = Module()
++        self.modules.append(module)
++
++        module.default_exception = self.module_state.module.default_exception
++        self.module_state = ModuleState(module, sip_file)
++
++        # Get the configuration of the new module.
++        mod_tags, mod_disabled = get_bindings_configuration(
++                self.spec.abi_version[0], sip_file, self._include_dirs)
++
++        for tag in mod_tags:
++            if tag not in self.tags:
++                self.tags.append(tag)
++
++        for feature in mod_disabled:
++            if feature not in self._disabled_features:
++                self._disabled_features.append(feature)
++
++        # Add the new import.
++        importing_from.imports.append(module)
++
+     def _read(self, sip_file, raw_sip_file):
+         """ Return the contents of the current .sip file. """
+ 
+@@ -2149,7 +2139,7 @@ class ParserManager:
+ class ModuleState:
+     """ Encapsulate the parser-related state for a module. """
+ 
+-    def __init__(self, module, sip_file, pm):
++    def __init__(self, module, sip_file):
+         """ Initialise the state. """
+ 
+         self.module = module
+@@ -2162,8 +2152,6 @@ class ModuleState:
+         self.kw_args = KwArgs.NONE
+         self.nr_timelines = 0
+ 
+-        pm.module_states.append(self)
+-
+ 
+ class ScopeState:
+     """ Encapsulate the parser-related state for a scope. """
+diff --git a/sipbuild/generator/parser/rules.py b/sipbuild/generator/parser/rules.py
+index 0c3ad03..9c804e0 100644
+--- a/sipbuild/generator/parser/rules.py
++++ b/sipbuild/generator/parser/rules.py
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2022, Riverbank Computing Limited
++# Copyright (c) 2023, Riverbank Computing Limited
+ # All rights reserved.
+ #
+ # This copy of SIP is licensed for use under the terms of the SIP License
+@@ -201,6 +201,12 @@ def p_composite_module(p):
+     if pm.skipping:
+         return
+ 
++    # A composite module must be the first one in the specification.
++    if not pm.in_main_module:
++        pm.parser_error(p, 1, "a %CompositeModule cannot be %Imported")
++
++    pm.spec.is_composite = True
++
+     if len(p) == 4:
+         name = p[2]
+         body = p[3]
+@@ -210,15 +216,7 @@ def p_composite_module(p):
+ 
+     module = pm.module_state.module
+ 
+-    if module is not pm.modules[0]:
+-        pm.parser_error(p, 1, "a %CompositeModule cannot be %Imported")
+-
+-    if module.fq_py_name is not None:
+-        pm.parser_error(p, 1,
+-                "%CompositeModule must appear before any %Module directive")
+-
+     module.fq_py_name = cached_name(pm.spec, str(name))
+-    module.is_composite = True
+ 
+     for directive in body:
+         if isinstance(directive, Docstring):
+@@ -1035,22 +1033,15 @@ def p_module(p):
+     if pm.skipping:
+         return
+ 
+-    module_state = pm.module_state
+-    module = module_state.module
+-
+     # See if this %Module is part of a %CompositeModule.
+-    if module.is_composite or module.composite is not None:
++    if pm.spec.is_composite:
+         # Historically we %Include modules although conceptually we actually
+         # %Import them.  Ensure that the scopes etc. are correct in either
+         # case.
+         pm.ensure_import()
+ 
+-        # The module state may have changed.
+-        module_state = pm.module_state
+-
+-        module_state.module.composite = module if module.is_composite else module.composite
+-
+-        module = module_state.module
++    module_state = pm.module_state
++    module = module_state.module
+ 
+     if module.fq_py_name is not None:
+         pm.parser_error(p, 1, "%Module has already been specified")
+diff --git a/sipbuild/generator/specification.py b/sipbuild/generator/specification.py
+index eecaaab..05a2dfb 100644
+--- a/sipbuild/generator/specification.py
++++ b/sipbuild/generator/specification.py
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2022, Riverbank Computing Limited
++# Copyright (c) 2023, Riverbank Computing Limited
+ # All rights reserved.
+ #
+ # This copy of SIP is licensed for use under the terms of the SIP License
+@@ -979,9 +979,6 @@ class Module:
+     # Set if wrapped ctors should support cooperative multi-inheritance.
+     call_super_init: bool = False
+ 
+-    # The containing composite module.
+-    composite: Optional['Module'] = None
+-
+     # The text specified by any %Copying directives.
+     copying: List[CodeBlock] = field(default_factory=list)
+ 
+@@ -1023,9 +1020,6 @@ class Module:
+     # The code specified by any %InitialisationCode directives.
+     initialisation_code: List[CodeBlock] = field(default_factory=list)
+ 
+-    # Set if the module is a composite module.
+-    is_composite: bool = False
+-
+     # The software license.
+     license: Optional[License] = None
+ 
+@@ -1316,6 +1310,9 @@ class Specification:
+     # The interface files.
+     iface_files: List[IfaceFile] = field(default_factory=list)
+ 
++    # Set if the specification is for a composite module.
++    is_composite: bool = False
++
+     # The mapped type templates.
+     mapped_type_templates: List[MappedTypeTemplate] = field(default_factory=list)
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 2792c84..1526b57 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
 intersphinx_local.diff
+composite_classes.diff



More information about the Neon-commits mailing list