[neon/forks/sip6/Neon/release] /: New upstream version 6.7.7+dfsg
Dmitry Shachnev
null at kde.org
Sun Feb 19 03:56:41 GMT 2023
Git commit d7431734eb9145d03cdae87b8dfd1bf996b44edc by Dmitry Shachnev.
Committed on 06/02/2023 at 13:17.
Pushed by carlosdem into branch 'Neon/release'.
New upstream version 6.7.7+dfsg
M +58 -0 ChangeLog
M +3 -0 NEWS
M +1 -1 PKG-INFO
M +6 -16 code_generator/gencode.c
M +2 -8 code_generator/py2c.c
M +2 -5 code_generator/sip.h
M +1 -1 sip.egg-info/PKG-INFO
M +2 -2 sipbuild/bindings.py
M +20 -13 sipbuild/generator/outputs/formatters/argument.py
M +10 -7 sipbuild/generator/outputs/formatters/value_list.py
M +4 -4 sipbuild/generator/outputs/pyi.py
M +34 -13 sipbuild/generator/outputs/type_hints.py
M +10 -5 sipbuild/generator/outputs/xml.py
M +4 -3 sipbuild/generator/parser/parser.py
M +39 -51 sipbuild/generator/parser/parser_manager.py
M +10 -19 sipbuild/generator/parser/rules.py
M +4 -7 sipbuild/generator/specification.py
M +2 -2 sipbuild/version.py
https://invent.kde.org/neon/forks/sip6/commit/d7431734eb9145d03cdae87b8dfd1bf996b44edc
diff --git a/ChangeLog b/ChangeLog
index d8122e9..68fc975 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,63 @@
+2023-02-04 Phil Thompson <phil at riverbankcomputing.com>
+
+ * sipbuild/generator/outputs/pyi.py:
+ In .pyi files generate implict imports as well as explicit imports.
+ [2d5cad50e879] [6.7.7] <6.7-maint>
+
+ * NEWS, sipbuild/generator/outputs/pyi.py:
+ Fixed the 'pyqtsignal' typo in generated .pyi files.
+ [48117db2851d] <6.7-maint>
+
+2023-02-02 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, sipbuild/generator/outputs/type_hints.py:
+ Use the standard Sphinx directive to reference voidptr.
+ [2c334836f75f] <6.7-maint>
+
+2023-02-01 Phil Thompson <phil at riverbankcomputing.com>
+
+ * sipbuild/generator/outputs/formatters/argument.py,
+ sipbuild/generator/outputs/type_hints.py,
+ sipbuild/generator/outputs/xml.py:
+ Ensure voidptr is rendered consistently and as a reST reference
+ where appropriate.
+ [3b892deb8c1b] <6.7-maint>
+
+ * sipbuild/generator/outputs/formatters/argument.py,
+ sipbuild/generator/outputs/formatters/value_list.py,
+ sipbuild/generator/outputs/xml.py:
+ Changes to the XML generation to reduce differences to earlier
+ versions.
+ [41dc32eadb62] <6.7-maint>
+
+2023-01-31 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, code_generator/gencode.c, code_generator/py2c.c,
+ code_generator/sip.h, sipbuild/bindings.py,
+ sipbuild/generator/outputs/pyi.py,
+ sipbuild/generator/parser/parser_manager.py,
+ sipbuild/generator/parser/rules.py,
+ sipbuild/generator/specification.py:
+ Refactored the handling of composite classes so that they are
+ populated properly.
+ [0afab92347b6] <6.7-maint>
+
+2023-01-28 Phil Thompson <phil at riverbankcomputing.com>
+
+ * sipbuild/generator/outputs/xml.py:
+ Fixes for regressions in the XML generation.
+ [77ebbacae72e] <6.7-maint>
+
+ * NEWS, sipbuild/generator/parser/parser.py:
+ Fixed an incorrect API comment.
+ [febcfb71804d] <6.7-maint>
+
2023-01-25 Phil Thompson <phil at riverbankcomputing.com>
+ * .hgtags:
+ Added tag 6.7.6 for changeset 67273f43bdbf
+ [fe69fc6295b7] <6.7-maint>
+
* NEWS, code_generator/py2c.c:
Reduce the use of the heap when converting from Python to C data
structures.
diff --git a/NEWS b/NEWS
index c2803b9..7ebca32 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+v6.7.7 4th February 2023
+ - Bug fixes.
+
v6.7.6 25th January 2023
- The latest version of ABI v13 is v13.4.1.
- The latest version of ABI v12 is v12.11.1.
diff --git a/PKG-INFO b/PKG-INFO
index d6b037b..17f093d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: sip
-Version: 6.7.6
+Version: 6.7.7
Summary: A Python bindings generator for C/C++ libraries
Home-page: https://www.riverbankcomputing.com/software/sip/
Author: Riverbank Computing Limited
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/sip.egg-info/PKG-INFO b/sip.egg-info/PKG-INFO
index d6b037b..17f093d 100644
--- a/sip.egg-info/PKG-INFO
+++ b/sip.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: sip
-Version: 6.7.6
+Version: 6.7.7
Summary: A Python bindings generator for C/C++ libraries
Home-page: https://www.riverbankcomputing.com/software/sip/
Author: Riverbank Computing Limited
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/formatters/argument.py b/sipbuild/generator/outputs/formatters/argument.py
index f060e85..22e637c 100644
--- a/sipbuild/generator/outputs/formatters/argument.py
+++ b/sipbuild/generator/outputs/formatters/argument.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
@@ -24,7 +24,7 @@
from ...scoped_name import STRIP_NONE
from ...specification import ArgumentType, ArrayArgument, ClassKey, ValueType
-from ..type_hints import TypeHintManager
+from ..type_hints import format_voidptr, TypeHintManager
from .base_formatter import BaseFormatter
from .utils import format_scoped_py_name
@@ -213,7 +213,13 @@ class ArgumentFormatter(BaseFormatter):
return s
- def py_default_value(self, embedded=False):
+ # The types that are implicitly pointers.
+ _IMPLICIT_POINTERS = (ArgumentType.PYOBJECT, ArgumentType.PYTUPLE,
+ ArgumentType.PYLIST, ArgumentType.PYDICT, ArgumentType.PYCALLABLE,
+ ArgumentType.PYSLICE, ArgumentType.PYTYPE, ArgumentType.CAPSULE,
+ ArgumentType.PYBUFFER, ArgumentType.PYENUM)
+
+ def py_default_value(self, type_name, embedded=False, as_xml=False):
""" Return the Python representation of the argument's default value.
"""
@@ -229,21 +235,21 @@ class ArgumentFormatter(BaseFormatter):
if len(arg.default_value) == 1 and arg.default_value[0].value_type is ValueType.NUMERIC:
value = arg.default_value[0].value
- if len(arg.derefs) > 0 and value == 0:
+ if value == 0 and ('voidptr' in type_name or len(arg.derefs) > 0 or arg.type in self._IMPLICIT_POINTERS):
return 'None'
if arg.type in (ArgumentType.BOOL, ArgumentType.CBOOL):
return 'True' if value else 'False'
return ValueListFormatter(self.spec, arg.default_value).py_expression(
- embedded=embedded)
+ embedded=embedded, as_xml=as_xml)
- def as_py_type(self, pep484=False, default_value=False):
+ def as_py_type(self, pep484=False, default_value=False, as_xml=False):
""" Return the argument as a Python type. """
arg = self.object
- scope, name = self._py_arg(pep484)
+ scope, name = self._py_arg(pep484, as_xml)
s = format_scoped_py_name(scope, name)
@@ -251,11 +257,11 @@ class ArgumentFormatter(BaseFormatter):
if arg.name is not None:
s += ' ' + arg.name.name
- s += '=' + self.py_default_value()
+ s += '=' + self.py_default_value(name)
return s
- def as_rest_ref(self, out):
+ def as_rest_ref(self, out, as_xml=False):
""" Return the argument as a reST reference. """
arg = self.object
@@ -280,9 +286,10 @@ class ArgumentFormatter(BaseFormatter):
# There would normally be a type hint.
s += "unknown-type"
else:
- s += self.as_py_type()
+ s += self.as_py_type(as_xml=as_xml)
else:
- s += TypeHintManager(self.spec).as_rest_ref(hint, out)
+ s += TypeHintManager(self.spec).as_rest_ref(hint, out,
+ as_xml=as_xml)
return s
@@ -337,7 +344,7 @@ class ArgumentFormatter(BaseFormatter):
return hint
- def _py_arg(self, pep484):
+ def _py_arg(self, pep484, as_xml):
""" Return an argument as a 2-tuple of scope and name. """
type = self.object.type
@@ -369,7 +376,7 @@ class ArgumentFormatter(BaseFormatter):
name = definition.base_name
elif type in (ArgumentType.STRUCT, ArgumentType.UNION, ArgumentType.VOID):
- name = sip_module + '.voidptr'
+ name = format_voidptr(self.spec, pep484, as_xml)
elif type in (ArgumentType.STRING, ArgumentType.SSTRING, ArgumentType.USTRING):
name = 'bytes'
diff --git a/sipbuild/generator/outputs/formatters/value_list.py b/sipbuild/generator/outputs/formatters/value_list.py
index 0de7314..93f759f 100644
--- a/sipbuild/generator/outputs/formatters/value_list.py
+++ b/sipbuild/generator/outputs/formatters/value_list.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
@@ -38,12 +38,13 @@ class ValueListFormatter(BaseFormatter):
return self._expression()
- def py_expression(self, embedded=False):
+ def py_expression(self, embedded=False, as_xml=False):
""" The Python representation of the value list as an expression. """
- return self._expression(as_python=True, embedded=embedded)
+ return self._expression(as_python=True, embedded=embedded,
+ as_xml=as_xml)
- def as_rest_ref(self):
+ def as_rest_ref(self, as_xml=False):
""" Return the Python representation of the value list as a reST
reference.
"""
@@ -90,7 +91,7 @@ class ValueListFormatter(BaseFormatter):
return None
- def _expression(self, as_python=False, embedded=False):
+ def _expression(self, as_python=False, embedded=False, as_xml=False):
""" The representation of the value list as an expression. """
s = ''
@@ -155,10 +156,12 @@ class ValueListFormatter(BaseFormatter):
s += arg_formatter.cpp_type()
args = [ValueListFormatter(self.spec, a)._expression(
- as_python=as_python, embedded=embedded)
+ as_python=as_python, embedded=embedded,
+ as_xml=as_xml)
for a in value.value.args]
- s += '(' + ', '.join(args) + ')'
+ separator = ',' if as_xml else ', '
+ s += '(' + separator.join(args) + ')'
elif value.value_type is ValueType.EMPTY:
s += '{}'
diff --git a/sipbuild/generator/outputs/pyi.py b/sipbuild/generator/outputs/pyi.py
index b554366..5f90773 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)
@@ -79,7 +79,7 @@ import {spec.sip_module}
imports = []
- for mod in module.imports:
+ for mod in module.all_imports:
parts = mod.fq_py_name.name.split('.')
if mod.fq_py_name.name == mod.py_name:
@@ -460,7 +460,7 @@ def _callable(pf, spec, module, member, overloads, is_method, defined,
scope = '' if module.py_name == 'QtCore' else 'QtCore.'
s = _indent(indent)
- s += f'{overload.common.py_name.name}: typing.ClassVar[{scope}pyqtsignal]\n'
+ s += f'{overload.common.py_name.name}: typing.ClassVar[{scope}pyqtSignal]\n'
pf.write(s)
return
diff --git a/sipbuild/generator/outputs/type_hints.py b/sipbuild/generator/outputs/type_hints.py
index 9a702dc..3ca02fd 100644
--- a/sipbuild/generator/outputs/type_hints.py
+++ b/sipbuild/generator/outputs/type_hints.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
@@ -132,7 +132,7 @@ class TypeHintManager:
return managed_type_hint.as_docstring
- def as_rest_ref(self, type_hint, out):
+ def as_rest_ref(self, type_hint, out, as_xml=False):
""" Return the type hint with appropriate reST references. """
managed_type_hint = self._get_managed_type_hint(type_hint, out)
@@ -140,7 +140,7 @@ class TypeHintManager:
# See if it needs rendering.
if managed_type_hint.as_rest_ref is None:
managed_type_hint.as_rest_ref = self._render(managed_type_hint,
- out, rest_ref=True)
+ out, rest_ref=True, as_xml=as_xml)
return managed_type_hint.as_rest_ref
@@ -276,21 +276,22 @@ class TypeHintManager:
return node
def _render(self, managed_type_hint, out, pep484=False, rest_ref=False,
- module=None, defined=None):
+ module=None, defined=None, as_xml=False):
""" Return a rendered type hint. """
self._parse(managed_type_hint, out)
if managed_type_hint.root is not None:
s = self._render_node(managed_type_hint.root, out, pep484,
- rest_ref, module, defined)
+ rest_ref, module, defined, as_xml)
else:
- s = self._maybe_any_object(managed_type_hint.type_hint,
- pep484=pep484)
+ s = self._maybe_any_object(managed_type_hint.type_hint, pep484,
+ as_xml)
return s
- def _render_node(self, node, out, pep484, rest_ref, module, defined):
+ def _render_node(self, node, out, pep484, rest_ref, module, defined,
+ as_xml):
""" Render a single node. """
if node.type is NodeType.TYPING:
@@ -303,7 +304,7 @@ class TypeHintManager:
if node.children is not None:
children = [self._render_node(c, out, pep484, rest_ref, module,
- defined) for c in node.children]
+ defined, as_xml) for c in node.children]
s += '[' + ', '.join(children) + ']'
@@ -332,7 +333,7 @@ class TypeHintManager:
s = formatter.fq_py_name
else:
- s = self._maybe_any_object(node.definition, pep484)
+ s = self._maybe_any_object(node.definition, pep484, as_xml)
return s
@@ -462,13 +463,19 @@ class TypeHintManager:
# Nothing was found.
return TypeHintNode(NodeType.OTHER, definition=name)
- @classmethod
- def _maybe_any_object(cls, hint, pep484):
+ def _maybe_any_object(self, hint, pep484, as_xml):
""" Return a hint taking into account that it may be any sort of
object.
"""
- return hint if hint != 'Any' else cls._any_object(pep484)
+ if hint == 'Any':
+ return cls._any_object(pep484)
+
+ # Don't worry if the voidptr name is qualified in any way.
+ if hint.endswith('voidptr'):
+ return format_voidptr(self._spec, pep484, as_xml)
+
+ return hint
@staticmethod
def _any_object(pep484):
@@ -495,3 +502,17 @@ class TypeHintManager:
end -= 1
return end
+
+
+def format_voidptr(spec, pep484, as_xml):
+ """ Return the representation of a voidptr in the context of either a type
+ hint, XML or a docstring.
+ """
+
+ if pep484:
+ return spec.sip_module + '.voidptr'
+
+ if as_xml:
+ return f':py:class:`~{spec.sip_module}.voidptr`'
+
+ return 'voidptr'
diff --git a/sipbuild/generator/outputs/xml.py b/sipbuild/generator/outputs/xml.py
index b92a848..c3cfc73 100644
--- a/sipbuild/generator/outputs/xml.py
+++ b/sipbuild/generator/outputs/xml.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
@@ -42,14 +42,16 @@ def output_xml(spec, module_name):
# Note that we don't yet handle mapped types, templates or exceptions.
- if spec.module.py_name != module_name:
+ module = spec.module
+
+ if module.py_name != module_name:
return None
root = Element('Module', version=_XML_VERSION_NR, name=module.py_name)
for klass in spec.classes:
if klass.iface_file.module is module and not klass.external:
- _xml_class(root, spec, module, klass)
+ _class(root, spec, module, klass)
for klass in module.proxies:
_class(root, spec, module, klass)
@@ -375,7 +377,9 @@ def _typename(spec, arg, kw_args=KwArgs.NONE, out=False):
if kw_args is KwArgs.ALL or (kw_args is KwArgs.OPTIONAL and arg.default_value is not None):
s += arg.name.name + ': '
- s += ArgumentFormatter(spec, arg).as_rest_ref(out)
+ arg_formatter = ArgumentFormatter(spec, arg)
+ arg_rest_ref = arg_formatter.as_rest_ref(out, as_xml=True)
+ s += arg_rest_ref
if not out and arg.name is not None and arg.default_value is not None:
s += ' = '
@@ -384,7 +388,8 @@ def _typename(spec, arg, kw_args=KwArgs.NONE, out=False):
# hard but will get most cases.
rest_ref = ValueListFormatter(spec, arg.default_value).as_rest_ref()
if rest_ref is None:
- rest_ref = formatter.py_default_value()
+ rest_ref = arg_formatter.py_default_value(arg_rest_ref,
+ as_xml=True)
s += rest_ref
diff --git a/sipbuild/generator/parser/parser.py b/sipbuild/generator/parser/parser.py
index 54e613f..9a15259 100644
--- a/sipbuild/generator/parser/parser.py
+++ b/sipbuild/generator/parser/parser.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
@@ -27,8 +27,9 @@ from .parser_manager import ParserManager
def parse(sip_file, hex_version, encoding, abi_version, tags,
disabled_features, protected_is_public, include_dirs, sip_module,
is_strict=True):
- """ Parse a .sip specification file returning a corresponding Specification
- object and a list of the .sip files that define the module to be generated.
+ """ Parse a .sip file and return a 3-tuple of a Specification object, a
+ list of Module objects and a list of the .sip files that specify the module
+ to be generated. A UserException is raised if there was an error.
"""
return ParserManager(
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/sipbuild/version.py b/sipbuild/version.py
index 4755178..2978308 100644
--- a/sipbuild/version.py
+++ b/sipbuild/version.py
@@ -1,2 +1,2 @@
-SIP_VERSION = 0x060706
-SIP_VERSION_STR = '6.7.6'
+SIP_VERSION = 0x060707
+SIP_VERSION_STR = '6.7.7'
More information about the Neon-commits
mailing list