[neon/forks/sip6/Neon/release] /: New upstream version 6.7.6+dfsg
Dmitry Shachnev
null at kde.org
Sat Feb 4 02:04:46 GMT 2023
Git commit 147325fbcc2a836d58c00e1b95a56ad35a9464ae by Dmitry Shachnev.
Committed on 28/01/2023 at 17:56.
Pushed by carlosdem into branch 'Neon/release'.
New upstream version 6.7.6+dfsg
M +72 -0 ChangeLog
M +4 -1 NEWS
M +1 -1 PKG-INFO
M +66 -59 code_generator/gencode.c
M +35 -41 code_generator/py2c.c
M +0 -1 code_generator/sip.h
M +1 -1 sip.egg-info/PKG-INFO
M +3 -3 sipbuild/bindings.py
M +1 -1 sipbuild/generator/outputs/api.py
M +32 -12 sipbuild/generator/outputs/pyi.py
M +1 -4 sipbuild/generator/outputs/xml.py
M +13 -9 sipbuild/generator/parser/parser_manager.py
M +1 -1 sipbuild/generator/parser/rules.py
M +46 -59 sipbuild/generator/resolver/resolver.py
M +2 -2 sipbuild/generator/specification.py
M +1 -1 sipbuild/module/source/12/sip.h.in
M +6 -1 sipbuild/module/source/12/siplib.c
M +1 -1 sipbuild/module/source/13/sip.h.in
M +1 -1 sipbuild/module/source/13/sip_core.c
M +2 -2 sipbuild/version.py
https://invent.kde.org/neon/forks/sip6/commit/147325fbcc2a836d58c00e1b95a56ad35a9464ae
diff --git a/ChangeLog b/ChangeLog
index 98554e6..d8122e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,75 @@
+2023-01-25 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, code_generator/py2c.c:
+ Reduce the use of the heap when converting from Python to C data
+ structures.
+ [67273f43bdbf] [6.7.6] <6.7-maint>
+
+2023-01-12 Phil Thompson <phil at riverbankcomputing.com>
+
+ * code_generator/gencode.c:
+ Fixed a regression so that enums are not registered if there is no
+ meta-object.
+ [f4ccf3303e59] <6.7-maint>
+
+ * NEWS, code_generator/gencode.c:
+ Ensure that all enums (including global enums) are registered with
+ Qt so that they can be used in queued connections.
+ [259096e57fd7] <6.7-maint>
+
+2022-12-16 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, sipbuild/module/source/13/sip.h.in,
+ sipbuild/module/source/13/sip_core.c:
+ Fixed the implementation of /Transfer/ for global functions in ABI
+ v13.
+ [bc56c45dd235] <6.7-maint>
+
+2022-12-14 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, sipbuild/module/source/12/sip.h.in,
+ sipbuild/module/source/12/siplib.c:
+ In API v12 prevent an attempt to sub-class from an enum. The API
+ version number is now v12.11.1.
+ [91cda197b6ca] <6.7-maint>
+
+ * NEWS, sipbuild/generator/outputs/pyi.py:
+ Fixed type hints when a signal is overloaded with a method.
+ [6343b9aeceb9] <6.7-maint>
+
+2022-12-13 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, sipbuild/generator/outputs/pyi.py:
+ Fixed the .pyi file for enums with no members.
+ [b828fb046720] <6.7-maint>
+
+2022-12-05 Phil Thompson <phil at riverbankcomputing.com>
+
+ * NEWS, sipbuild/generator/outputs/pyi.py:
+ Fixed the representation of Qt signals in the .pyi files.
+ [ba2933733f6c] <6.7-maint>
+
+2022-11-21 Phil Thompson <phil at riverbankcomputing.com>
+
+ * code_generator/gencode.c, code_generator/py2c.c,
+ code_generator/sip.h, sipbuild/bindings.py,
+ sipbuild/generator/outputs/api.py,
+ sipbuild/generator/outputs/pyi.py,
+ sipbuild/generator/outputs/xml.py,
+ sipbuild/generator/parser/parser_manager.py,
+ sipbuild/generator/parser/rules.py,
+ sipbuild/generator/resolver/resolver.py,
+ sipbuild/generator/specification.py:
+ Re-factored Specification so that it just has the module that code
+ will be generated for rather than a list of all modules.
+ [be55cf9e3e79] <6.7-maint>
+
+2022-11-19 Phil Thompson <phil at riverbankcomputing.com>
+
+ * .hgtags:
+ Added tag 6.7.5 for changeset 43c1391748cf
+ [bc0278714cdd] <6.7-maint>
+
2022-11-15 Phil Thompson <phil at riverbankcomputing.com>
* NEWS, sipbuild/generator/outputs/extracts.py:
diff --git a/NEWS b/NEWS
index 3009588..c2803b9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,7 @@
-v6.7.5 15th November 2022
+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.
+ - Significantly reduced the memory requirements.
- Bug fixes.
v6.7.4 29th October 2022
diff --git a/PKG-INFO b/PKG-INFO
index 9b814a8..d6b037b 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: sip
-Version: 6.7.5
+Version: 6.7.6
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 0ca5354..9fc917c 100644
--- a/code_generator/gencode.c
+++ b/code_generator/gencode.c
@@ -461,6 +461,61 @@ void generateExpression(valueDef *vd, int in_str, FILE *fp)
}
+/*
+ * Generate the #defines for each feature defined in a module.
+ */
+static int generateFeatureDefines(moduleDef *mod,
+ stringList *needed_qualifiers, stringList *xsl, int noIntro, FILE *fp)
+{
+ qualDef *qd;
+
+ for (qd = mod->qualifiers; qd != NULL; qd = qd->next)
+ {
+ const char *qtype = NULL;
+
+ switch (qd->qtype)
+ {
+ case time_qualifier:
+ if (selectedQualifier(needed_qualifiers, qd))
+ qtype = "TIMELINE";
+
+ break;
+
+ case platform_qualifier:
+ if (selectedQualifier(needed_qualifiers, qd))
+ qtype = "PLATFORM";
+
+ break;
+
+ case feature_qualifier:
+ if (!excludedFeature(xsl, qd))
+ qtype = "FEATURE";
+
+ break;
+ }
+
+ if (qtype != NULL)
+ {
+ if (noIntro)
+ {
+ prcode(fp,
+"\n"
+"/* These are the qualifiers that are enabled. */\n"
+ );
+
+ noIntro = FALSE;
+ }
+
+ prcode(fp,
+"#define SIP_%s_%s\n"
+ , qtype, qd->name);
+ }
+ }
+
+ return noIntro;
+}
+
+
/*
* Generate the C++ internal module API header file and return its path name on
* the heap.
@@ -474,7 +529,6 @@ static const char *generateInternalAPIHeader(sipSpec *pt, moduleDef *mod,
int noIntro;
FILE *fp;
nameDef *nd;
- moduleDef *imp;
moduleListDef *mld;
hfile = concat(codeDir, "/sipAPI", mname, ".h", NULL);
@@ -504,55 +558,11 @@ static const char *generateInternalAPIHeader(sipSpec *pt, moduleDef *mod,
);
/* Define the qualifiers. */
- noIntro = TRUE;
-
- for (imp = pt->modules; imp != NULL; imp = imp->next)
- {
- qualDef *qd;
-
- for (qd = imp->qualifiers; qd != NULL; qd = qd->next)
- {
- const char *qtype = NULL;
-
- switch (qd->qtype)
- {
- case time_qualifier:
- if (selectedQualifier(needed_qualifiers, qd))
- qtype = "TIMELINE";
-
- break;
+ noIntro = generateFeatureDefines(mod, needed_qualifiers, xsl, TRUE, fp);
- case platform_qualifier:
- if (selectedQualifier(needed_qualifiers, qd))
- qtype = "PLATFORM";
-
- break;
-
- case feature_qualifier:
- if (!excludedFeature(xsl, qd))
- qtype = "FEATURE";
-
- break;
- }
-
- if (qtype != NULL)
- {
- if (noIntro)
- {
- prcode(fp,
-"\n"
-"/* These are the qualifiers that are enabled. */\n"
- );
-
- noIntro = FALSE;
- }
-
- prcode(fp,
-"#define SIP_%s_%s\n"
- , qtype, qd->name);
- }
- }
- }
+ for (mld = mod->allimports; mld != NULL; mld = mld->next)
+ noIntro = generateFeatureDefines(mld->module, needed_qualifiers, xsl,
+ noIntro, fp);
if (!noIntro)
prcode(fp,
@@ -1034,7 +1044,7 @@ static int generateCompositeCpp(sipSpec *pt, const char *codeDir,
stringList **generated, int py_debug)
{
char *cppfile;
- moduleDef *mod;
+ moduleListDef *mld;
FILE *fp;
cppfile = concat(codeDir, "/sip", pt->module->name, "cmodule.c", NULL);
@@ -1087,11 +1097,11 @@ static int generateCompositeCpp(sipSpec *pt, const char *codeDir,
"\n"
);
- for (mod = pt->modules; mod != NULL; mod = mod->next)
- if (mod->container == pt->module)
+ for (mld = pt->module->allimports; mld != NULL; mld = mld->next)
+ if (mld->module->container == pt->module)
prcode(fp,
" sip_import_component_module(sipModuleDict, \"%s\");\n"
- , mod->fullname->text);
+ , mld->module->fullname->text);
prcode(fp,
"\n"
@@ -2169,11 +2179,8 @@ static const char *generateCpp(sipSpec *pt, moduleDef *mod,
, mname, mod->nrexceptions);
/*
- * Generate the enum meta-type registrations for PyQt6. Qt6 registers
- * these as and when it needs them which means that PyQt6 might handle them
- * differently at different times. It can be a particular problem with
- * QMetaObject.invokeMethod(). The safest option is to register them all
- * at the start.
+ * Generate the enum meta-type registrations for PyQt6 so that they can be
+ * used in queued connections.
*/
if (pluginPyQt6(pt))
{
@@ -2185,7 +2192,7 @@ static const char *generateCpp(sipSpec *pt, moduleDef *mod,
if (isProtectedEnum(ed))
continue;
- if (ed->ecd == NULL || noPyQtQMetaObject(ed->ecd))
+ if (ed->ecd != NULL && noPyQtQMetaObject(ed->ecd))
continue;
prcode(fp,
diff --git a/code_generator/py2c.c b/code_generator/py2c.c
index af2f708..2e6b3f3 100644
--- a/code_generator/py2c.c
+++ b/code_generator/py2c.c
@@ -234,9 +234,10 @@ static void *search_str_cache(const strCache *cache, char *py_str)
/* Forward declarations of convertors. */
-static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding);
-static argDef *argument_attr(sipSpec *pt, PyObject *obj, const char *name,
- const char *encoding);
+static void argument(sipSpec *pt, PyObject *obj, const char *encoding,
+ argDef *value);
+static void argument_attr(sipSpec *pt, PyObject *obj, const char *name,
+ const char *encoding, argDef *value);
static argList *argument_list_attr(sipSpec *pt, PyObject *obj,
const char *name, const char *encoding);
static int bool_attr(PyObject *obj, const char *name);
@@ -319,9 +320,9 @@ static scopedNameDef *scopedname(PyObject *obj, const char *encoding);
static scopedNameDef *scopedname_attr(PyObject *obj, const char *name,
const char *encoding);
static signatureDef *signature(sipSpec *pt, PyObject *obj,
- const char *encoding);
+ const char *encoding, signatureDef *value);
static signatureDef *signature_attr(sipSpec *pt, PyObject *obj,
- const char *name, const char *encoding);
+ const char *name, const char *encoding, signatureDef *value);
static sourceLocation sourcelocation(PyObject *obj, const char *encoding);
static sourceLocation sourcelocation_attr(PyObject *obj, const char *name,
const char *encoding);
@@ -398,8 +399,7 @@ sipSpec *py2c(PyObject *spec, const char *encoding)
pt = sipMalloc(sizeof (sipSpec));
- pt->modules = module_list_attr(pt, spec, "modules", encoding);
- pt->module = pt->modules;
+ pt->module = module_attr(pt, spec, "module", encoding);
pt->namecache = cachedname_list_attr(spec, "name_cache", encoding);
pt->ifacefiles = ifacefile_list_attr(pt, spec, "iface_files", encoding);
pt->classes = class_list_attr(pt, spec, "classes", encoding);
@@ -428,9 +428,9 @@ sipSpec *py2c(PyObject *spec, const char *encoding)
/*
* Convert an optional Argument object.
*/
-static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
+static void argument(sipSpec *pt, PyObject *obj, const char *encoding,
+ argDef *value)
{
- argDef *value = sipMalloc(sizeof (argDef));
PyObject *derefs_obj, *definition;
int key, xfer, array;
Py_ssize_t i;
@@ -438,7 +438,7 @@ static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
if (obj == Py_None)
{
value->atype = no_type;
- return value;
+ return;
}
value->atype = (argType)enum_attr(obj, "type");
@@ -523,7 +523,7 @@ static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
switch (value->atype)
{
case function_type:
- value->u.sa = signature(pt, definition, encoding);
+ value->u.sa = signature(pt, definition, encoding, NULL);
break;
case template_type:
@@ -560,27 +560,22 @@ static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
}
Py_DECREF(definition);
-
- return value;
}
/*
* Convert an optional Argument attribute.
*/
-static argDef *argument_attr(sipSpec *pt, PyObject *obj, const char *name,
- const char *encoding)
+static void argument_attr(sipSpec *pt, PyObject *obj, const char *name,
+ const char *encoding, argDef *value)
{
PyObject *attr = PyObject_GetAttrString(obj, name);
- argDef *value;
assert(attr != NULL);
- value = argument(pt, attr, encoding);
+ argument(pt, attr, encoding, value);
Py_DECREF(attr);
-
- return value;
}
@@ -603,7 +598,7 @@ static argList *argument_list_attr(sipSpec *pt, PyObject *obj,
{
argList *item = sipMalloc(sizeof (argList));
- item->arg = *argument(pt, PyList_GetItem(attr, i), encoding);
+ argument(pt, PyList_GetItem(attr, i), encoding, &item->arg);
*tail = item;
tail = &item->next;
@@ -1046,7 +1041,7 @@ static ctorDef *constructor(sipSpec *pt, PyObject *obj, const char *encoding)
py_sig_obj = PyObject_GetAttrString(obj, "py_signature");
assert(py_sig_obj != NULL);
- value->pysig = *signature(pt, py_sig_obj, encoding);
+ signature(pt, py_sig_obj, encoding, &value->pysig);
cpp_sig_obj = PyObject_GetAttrString(obj, "cpp_signature");
assert(cpp_sig_obj != NULL);
@@ -1056,7 +1051,7 @@ static ctorDef *constructor(sipSpec *pt, PyObject *obj, const char *encoding)
if (cpp_sig_obj == py_sig_obj)
value->cppsig = &value->pysig;
else
- value->cppsig = signature(pt, cpp_sig_obj, encoding);
+ value->cppsig = signature(pt, cpp_sig_obj, encoding, NULL);
}
Py_DECREF(py_sig_obj);
@@ -1272,7 +1267,7 @@ static fcallDef *functioncall(sipSpec *pt, PyObject *obj, const char *encoding)
PyObject *args_obj;
Py_ssize_t i;
- value->type = *argument_attr(pt, obj, "result", encoding);
+ argument_attr(pt, obj, "result", encoding, &value->type);
args_obj = PyObject_GetAttrString(obj, "args");
assert(args_obj != NULL);
@@ -1482,7 +1477,7 @@ static mappedTypeDef *mappedtype(sipSpec *pt, PyObject *obj,
if (bool_attr(obj, "needs_user_state"))
setNeedsUserState(value);
- value->type = *argument_attr(pt, obj, "type", encoding);
+ argument_attr(pt, obj, "type", encoding, &value->type);
value->pyname = cachedname_attr(obj, "py_name", encoding);
value->cname = cachedname_attr(obj, "cpp_name", encoding);
typehints_attr(obj, "type_hints", encoding, &value->typehint_in,
@@ -1719,8 +1714,8 @@ static moduleDef *module(sipSpec *pt, PyObject *obj, const char *encoding)
value->needed_types = sipCalloc(nr_needed_types, sizeof (argDef));
for (i = 0; i < nr_needed_types; ++i)
- value->needed_types[i] = *argument(pt,
- PyList_GetItem(needed_types_obj, i), encoding);
+ argument(pt, PyList_GetItem(needed_types_obj, i), encoding,
+ &value->needed_types[i]);
value->nr_needed_types = nr_needed_types;
}
@@ -1938,7 +1933,7 @@ static overDef *over(sipSpec *pt, PyObject *obj, const char *encoding)
py_sig_obj = PyObject_GetAttrString(obj, "py_signature");
assert(py_sig_obj != NULL);
- value->pysig = *signature(pt, py_sig_obj, encoding);
+ signature(pt, py_sig_obj, encoding, &value->pysig);
cpp_sig_obj = PyObject_GetAttrString(obj, "cpp_signature");
assert(cpp_sig_obj != NULL);
@@ -1946,7 +1941,7 @@ static overDef *over(sipSpec *pt, PyObject *obj, const char *encoding)
if (cpp_sig_obj == py_sig_obj)
value->cppsig = &value->pysig;
else
- value->cppsig = signature(pt, cpp_sig_obj, encoding);
+ value->cppsig = signature(pt, cpp_sig_obj, encoding, NULL);
Py_DECREF(py_sig_obj);
Py_DECREF(cpp_sig_obj);
@@ -2170,25 +2165,25 @@ static scopedNameDef *scopedname_attr(PyObject *obj, const char *name,
* Convert an optional Signature object.
*/
static signatureDef *signature(sipSpec *pt, PyObject *obj,
- const char *encoding)
+ const char *encoding, signatureDef *value)
{
- signatureDef *value;
PyObject *args_obj;
Py_ssize_t i;
if (obj == Py_None)
return NULL;
- value = sipMalloc(sizeof (signatureDef));
+ if (value == NULL)
+ value = sipMalloc(sizeof (signatureDef));
- value->result = *argument_attr(pt, obj, "result", encoding);
+ argument_attr(pt, obj, "result", encoding, &value->result);
args_obj = PyObject_GetAttrString(obj, "args");
assert(args_obj != NULL);
assert(PyList_Check(args_obj));
for (i = 0; i < PyList_Size(args_obj) && i < MAX_NR_ARGS; ++i)
- value->args[i] = *argument(pt, PyList_GetItem(args_obj, i), encoding);
+ argument(pt, PyList_GetItem(args_obj, i), encoding, &value->args[i]);
value->nrArgs = i;
@@ -2202,14 +2197,13 @@ static signatureDef *signature(sipSpec *pt, PyObject *obj,
* Convert an optional Signature attribute.
*/
static signatureDef *signature_attr(sipSpec *pt, PyObject *obj,
- const char *name, const char *encoding)
+ const char *name, const char *encoding, signatureDef *value)
{
PyObject *attr = PyObject_GetAttrString(obj, name);
- signatureDef *value;
assert(attr != NULL);
- value = signature(pt, attr, encoding);
+ value = signature(pt, attr, encoding, value);
Py_DECREF(attr);
@@ -2337,7 +2331,7 @@ static templateDef *template(sipSpec *pt, PyObject *obj, const char *encoding)
value = sipMalloc(sizeof (templateDef));
value->fqname = scopedname_attr(obj, "cpp_name", encoding);
- value->types = *signature_attr(pt, obj, "types", encoding);
+ signature_attr(pt, obj, "types", encoding, &value->types);
return value;
}
@@ -2678,8 +2672,8 @@ static virtHandlerDef *virtualhandler(sipSpec *pt, PyObject *obj,
value = sipMalloc(sizeof (virtHandlerDef));
- value->cppsig = signature_attr(pt, obj, "cpp_signature", encoding);
- value->pysig = signature_attr(pt, obj, "py_signature", encoding);
+ value->cppsig = signature_attr(pt, obj, "cpp_signature", encoding, NULL);
+ value->pysig = signature_attr(pt, obj, "py_signature", encoding, NULL);
value->virtcode = codeblock_list_attr(obj, "virtual_catcher_code",
encoding);
value->veh = virtualerrorhandler_attr(pt, obj, "virtual_error_handler",
@@ -3031,7 +3025,7 @@ static typedefDef *wrappedtypedef(sipSpec *pt, PyObject *obj,
value->fqname = scopedname_attr(obj, "fq_cpp_name", encoding);
value->ecd = class_attr(pt, obj, "scope", encoding);
value->module = module_attr(pt, obj, "module", encoding);
- value->type = *argument_attr(pt, obj, "type", encoding);
+ argument_attr(pt, obj, "type", encoding, &value->type);
return value;
}
@@ -3107,7 +3101,7 @@ static varDef *wrappedvariable(sipSpec *pt, PyObject *obj,
if (bool_attr(obj, "needs_handler"))
setNeedsHandler(value);
- value->type = *argument_attr(pt, obj, "type", encoding);
+ argument_attr(pt, obj, "type", encoding, &value->type);
value->accessfunc = codeblock_list_attr(obj, "access_code", encoding);
value->getcode = codeblock_list_attr(obj, "get_code", encoding);
value->setcode = codeblock_list_attr(obj, "set_code", encoding);
diff --git a/code_generator/sip.h b/code_generator/sip.h
index 31fcbb0..23b3f49 100644
--- a/code_generator/sip.h
+++ b/code_generator/sip.h
@@ -1259,7 +1259,6 @@ typedef struct _autoPyNameDef {
/* The parse tree corresponding to the specification file. */
typedef struct {
moduleDef *module; /* The module being generated. */
- moduleDef *modules; /* The list of modules. */
nameDef *namecache; /* The name cache. */
ifaceFileDef *ifacefiles; /* The list of interface files. */
classDef *classes; /* The list of classes. */
diff --git a/sip.egg-info/PKG-INFO b/sip.egg-info/PKG-INFO
index 9b814a8..d6b037b 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.5
+Version: 6.7.6
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 7f0a40e..a2346c7 100644
--- a/sipbuild/bindings.py
+++ b/sipbuild/bindings.py
@@ -163,17 +163,17 @@ class Bindings(Configurable):
encoding = 'UTF-8'
# Parse the input file.
- spec, sip_files = parse(self.sip_file, SIP_VERSION, encoding,
+ spec, modules, sip_files = parse(self.sip_file, SIP_VERSION, encoding,
project.abi_version, self.tags, self.disabled_features,
self.protected_is_public, self._sip_include_dirs,
project.sip_module or 'sip')
# Resolve the types.
- resolve(spec)
+ resolve(spec, modules)
pt = py2c(spec, encoding)
- module = spec.modules[0]
+ module = spec.module
uses_limited_api = module.use_limited_api or module.is_composite
diff --git a/sipbuild/generator/outputs/api.py b/sipbuild/generator/outputs/api.py
index 4a5fde0..b76e601 100644
--- a/sipbuild/generator/outputs/api.py
+++ b/sipbuild/generator/outputs/api.py
@@ -44,7 +44,7 @@ def output_api(spec, api_filename):
""" Output a QScintilla API file. """
with open(api_filename, 'w') as af:
- module = spec.modules[0]
+ module = spec.module
_enums(af, spec, module)
_variables(af, spec, module)
diff --git a/sipbuild/generator/outputs/pyi.py b/sipbuild/generator/outputs/pyi.py
index f601b9c..b554366 100644
--- a/sipbuild/generator/outputs/pyi.py
+++ b/sipbuild/generator/outputs/pyi.py
@@ -24,7 +24,7 @@
from ...version import SIP_VERSION_STR
from ..specification import (AccessSpecifier, ArgumentType, ArrayArgument,
- EnumBaseType, IfaceFileType, PySlot)
+ EnumBaseType, IfaceFileType, PyQtMethodSpecifier, PySlot)
from ..utils import append_iface_file, find_method
from .formatters import (ArgumentFormatter, ClassFormatter, format_copying,
@@ -35,7 +35,7 @@ def output_pyi(spec, pyi_filename):
""" Output a .pyi file. """
with open(pyi_filename, 'w') as pf:
- module = spec.modules[0]
+ module = spec.module
# Write the header.
copying = format_copying(module.copying, '#')
@@ -58,8 +58,8 @@ f'''# The PEP 484 type hints stub file for the {module.py_name} module.
def _composite_module(pf, spec, module):
""" Output the type hints for a composite module. """
- for mod in spec.modules:
- if mod.composite is module:
+ for mod in spec.module.all_imports:
+ if mod.composite is spec.module:
pf.write(f'from {mod.fq_py_name.name} import *\n')
@@ -386,8 +386,16 @@ def _enums(pf, spec, module, defined=None, scope=None, indent=0):
elif enum.base_type is EnumBaseType.INT_FLAG:
superclass = 'enum.IntFlag'
+ # Handle an enum with no members.
+ for member in enum.members:
+ if not member.no_type_hint:
+ trivial = ''
+ break
+ else:
+ trivial = ' ...'
+
s = _indent(indent)
- s+= f'class {enum.py_name.name}({superclass}):\n'
+ s+= f'class {enum.py_name.name}({superclass}):{trivial}\n'
pf.write(s)
indent += 1
@@ -395,12 +403,10 @@ def _enums(pf, spec, module, defined=None, scope=None, indent=0):
enum_type = 'int'
for member in enum.members:
- if member.no_type_hint:
- continue
-
- s = _indent(indent)
- s += f'{member.py_name.name} = ... # type: {enum_type}\n'
- pf.write(s)
+ if not member.no_type_hint:
+ s = _indent(indent)
+ s += f'{member.py_name.name} = ... # type: {enum_type}\n'
+ pf.write(s)
if enum.py_name is not None:
indent -= 1
@@ -447,6 +453,18 @@ def _callable(pf, spec, module, member, overloads, is_method, defined,
if overload.no_type_hint:
continue
+ # Signals can have the same name as ordinary methods however
+ # 'typing.overload' cannot be used with ClassVar. We choose to
+ # generate a type hint for the signal rather than any method.
+ if overload.pyqt_method_specifier is PyQtMethodSpecifier.SIGNAL:
+ scope = '' if module.py_name == 'QtCore' else 'QtCore.'
+
+ s = _indent(indent)
+ s += f'{overload.common.py_name.name}: typing.ClassVar[{scope}pyqtsignal]\n'
+ pf.write(s)
+
+ return
+
nr_overloads += 1
# Handle each overload.
@@ -518,6 +536,8 @@ def _overload(pf, spec, module, overload, overloaded, overload_nr, is_method,
if is_method and overload.is_static:
pf.write(_indent(indent) + '@staticmethod\n')
+ s = _indent(indent)
+
if is_eq_slot:
signature = '(self, other: object)'
else:
@@ -526,8 +546,8 @@ def _overload(pf, spec, module, overload, overloaded, overload_nr, is_method,
signature = _python_signature(spec, module, overload.py_signature,
defined, need_self=need_self)
- s = _indent(indent)
s += f'def {overload.common.py_name.name}{signature}: ...\n'
+
pf.write(s)
diff --git a/sipbuild/generator/outputs/xml.py b/sipbuild/generator/outputs/xml.py
index c180395..b92a848 100644
--- a/sipbuild/generator/outputs/xml.py
+++ b/sipbuild/generator/outputs/xml.py
@@ -42,10 +42,7 @@ def output_xml(spec, module_name):
# Note that we don't yet handle mapped types, templates or exceptions.
- for module in spec.modules:
- if module.py_name == module_name:
- break
- else:
+ if spec.module.py_name != module_name:
return None
root = Element('Module', version=_XML_VERSION_NR, name=module.py_name)
diff --git a/sipbuild/generator/parser/parser_manager.py b/sipbuild/generator/parser/parser_manager.py
index b55c5f6..6608f75 100644
--- a/sipbuild/generator/parser/parser_manager.py
+++ b/sipbuild/generator/parser/parser_manager.py
@@ -81,6 +81,9 @@ class ParserManager:
tuple([int(v) for v in abi_version.split('.')]), is_strict,
sip_module)
+ # The module is initially unnamed.
+ self.modules = [self.spec.module]
+
self.c_bindings = None
self.code_block = None
self.module_state = None
@@ -1207,7 +1210,7 @@ class ParserManager:
# The current file was %Included so create a new Module and
# ModuleState as if it had been %Imported.
module = Module()
- self.spec.modules.append(module)
+ self.modules.append(module)
self.module_state = ModuleState(module, self._sip_file, self)
self._file_stack.append(
@@ -1317,7 +1320,7 @@ class ParserManager:
def find_qualifier(self, p, symbol, name, required=True):
""" Return a Qualifier or None if one doesn't exist. """
- for module in self.spec.modules:
+ for module in self.modules:
for qual in module.qualifiers:
if qual.name == name:
return qual
@@ -1458,7 +1461,7 @@ class ParserManager:
module = self.module_state.module
- return module is self.spec.modules[0] or module.composite is not None
+ return module is self.spec.module or module.composite is not None
def instantiate_class_template(self, p, symbol, fq_cpp_name, template,
py_name, no_type_name, docstring):
@@ -1487,9 +1490,10 @@ class ParserManager:
column=self._get_column_from_lexpos(t.lexpos)))
def parse(self, sip_file):
- """ Parse a .sip file and return a Specification object and a list of
- the .sip files that specify the module to be generated. A
- UserException is raised if there was an error.
+ """ 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.
"""
# Note that the retention of the 'raw' filename, ie. that which was
@@ -1499,7 +1503,7 @@ class ParserManager:
raw_sip_file = sip_file
sip_file = os.path.abspath(sip_file)
- self.module_state = ModuleState(self.spec.modules[0], sip_file, self)
+ self.module_state = ModuleState(self.spec.module, sip_file, self)
try:
self._parser.parse(self._read(sip_file, raw_sip_file),
@@ -1538,7 +1542,7 @@ class ParserManager:
for klass in self._template_arg_classes:
self.spec.classes.remove(klass)
- return self.spec, self._sip_files
+ return self.spec, self.modules, self._sip_files
def parser_error(self, p, symbol, text):
""" Record an error caused by a symbol in a production. """
@@ -1643,7 +1647,7 @@ class ParserManager:
break
else:
module = Module()
- self.spec.modules.append(module)
+ self.modules.append(module)
module.default_exception = self.module_state.module.default_exception
old_module_state = self.module_state
diff --git a/sipbuild/generator/parser/rules.py b/sipbuild/generator/parser/rules.py
index feea8d5..0c3ad03 100644
--- a/sipbuild/generator/parser/rules.py
+++ b/sipbuild/generator/parser/rules.py
@@ -210,7 +210,7 @@ def p_composite_module(p):
module = pm.module_state.module
- if module is not pm.spec.modules[0]:
+ 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:
diff --git a/sipbuild/generator/resolver/resolver.py b/sipbuild/generator/resolver/resolver.py
index 6097a78..e5fdd06 100644
--- a/sipbuild/generator/resolver/resolver.py
+++ b/sipbuild/generator/resolver/resolver.py
@@ -41,7 +41,7 @@ from ..utils import (append_iface_file, argument_as_str, cached_name,
same_signature, search_typedefs)
-def resolve(spec):
+def resolve(spec, modules):
""" Resolve all types of a parsed specification and create additional views
so that code can be generated.
"""
@@ -49,7 +49,7 @@ def resolve(spec):
error_log = ErrorLog()
# Build the list of all imports for each module.
- for mod in spec.modules:
+ for mod in modules:
_set_all_imports(mod, error_log)
# Set the base name of the module. This is done for efficiency.
@@ -57,19 +57,18 @@ def resolve(spec):
# Set the default meta-type for the main module if it doesn't have one
# explicitly set.
- main_mod = spec.modules[0]
-
- if main_mod.default_metatype is None:
- for mod in main_mod.all_imports:
+ if spec.module.default_metatype is None:
+ for mod in spec.module.all_imports:
if mod.default_metatype is None:
continue
- if main_mod.default_metatype is None:
- main_mod.default_metatype = mod.default_metatype
- elif main_mod.default_metatype is not mod.default_metatype:
+ if spec.module.default_metatype is None:
+ spec.module.default_metatype = mod.default_metatype
+ elif spec.module.default_metatype is not mod.default_metatype:
error_log.log(
"'{0}' module has imported different default meta-types '{1}' and '{2}'".format(
- main_mod.fq_py_name, main_mod.default_metatype,
+ spec.module.fq_py_name,
+ spec.module.default_metatype,
mod.default_metatype))
# Check each class has been defined.
@@ -95,7 +94,7 @@ def resolve(spec):
_set_mro(spec, klass, error_log)
# Resolve the various types in the modules.
- _resolve_module(spec, spec.modules[0], error_log)
+ _resolve_module(spec, spec.module, error_log)
# Handle default ctors now that the argument types are resolved.
for klass in spec.classes:
@@ -112,18 +111,14 @@ def resolve(spec):
# Move casts and slots around to their correct classes (if in the same
# module) or create proxies for them (if cross-module).
- for mod in spec.modules:
- if _generating_code_for_module(spec, mod):
- _move_main_module_casts_slots(spec, mod, error_log)
+ _move_main_module_casts_slots(spec, error_log)
# Automatically generate missing complementary slots.
for klass in spec.classes:
_add_complementary_slots(spec, klass)
- for mod in spec.modules:
- if _generating_code_for_module(spec, mod):
- for klass in mod.proxies:
- _add_complementary_slots(spec, klass)
+ for klass in spec.module.proxies:
+ _add_complementary_slots(spec, klass)
# Generate the different class views.
for klass in spec.classes:
@@ -143,7 +138,7 @@ def resolve(spec):
_iface_files_are_used_by_overload(spec, klass.iface_file.used,
overload)
- for mod in spec.modules:
+ for mod in modules:
# Create the list of numbered types sorted by type name.
_create_sorted_numbered_types(spec, mod, error_log)
@@ -166,8 +161,8 @@ def resolve(spec):
# Include the %TypeHeaderCode for exceptions defined in the main
# module.
if spec.abi_version >= (13, 1) or (spec.abi_version >= (12, 9) and spec.abi_version < (13, 0)):
- if exception_mod is spec.modules[0]:
- append_iface_file(spec.modules[0].used, exception.iface_file)
+ if exception_mod is spec.module:
+ append_iface_file(spec.module.used, exception.iface_file)
# Skip those that don't require a Python exception object to be
# created.
@@ -177,15 +172,15 @@ def resolve(spec):
if exception.builtin_base_exception is None and exception.defined_base_exception is None:
continue
- if exception_mod is spec.modules[0] or exception.needed:
+ if exception_mod is spec.module or exception.needed:
exception.exception_nr = exception_mod.nr_exceptions
exception_mod.nr_exceptions += 1
# For PyQt6 mark all enum interface files as being used.
if 'PyQt6' in spec.plugins:
for enum in spec.enums:
- if enum.module is spec.modules[0]:
- _enum_iface_file_is_used(enum, spec.modules[0])
+ if enum.module is spec.module:
+ _enum_iface_file_is_used(enum, spec.module)
# Create the name cache as seen by the legacy code.
name_cache = spec.name_cache
@@ -411,21 +406,21 @@ def _set_all_imports(mod, error_log, seen=None):
seen.remove(mod)
-def _move_main_module_casts_slots(spec, mod, error_log):
+def _move_main_module_casts_slots(spec, error_log):
""" Move the casts and slots to the correct place for a main module (ie.
the one we are generating code for).
"""
for klass in spec.classes:
- if klass.iface_file.module is mod:
- _move_class_casts(spec, mod, klass, error_log)
+ if klass.iface_file.module is spec.module:
+ _move_class_casts(spec, klass, error_log)
- for member in mod.global_functions:
- if member.py_slot is not None and member.module is mod:
- _move_global_slot(spec, mod, member, error_log)
+ for member in spec.module.global_functions:
+ if member.py_slot is not None and member.module is spec.module:
+ _move_global_slot(spec, member, error_log)
-def _move_class_casts(spec, mod, klass, error_log):
+def _move_class_casts(spec, klass, error_log):
""" Move any class casts to its correct class, or publish as a ctor
extender.
"""
@@ -443,9 +438,9 @@ def _move_class_casts(spec, mod, klass, error_log):
cpp_signature=signature, is_cast=True)
# If the destination class is in a different module then use a proxy.
- if dst_klass.iface_file.module is not mod:
- _iface_file_is_used(mod.used, arg)
- dst_klass = _get_proxy(mod, dst_klass)
+ if dst_klass.iface_file.module is not spec.module:
+ _iface_file_is_used(spec.module.used, arg)
+ dst_klass = _get_proxy(spec.module, dst_klass)
ctor.no_typehint = True
_iface_file_is_used(dst_klass.iface_file.used, arg)
@@ -461,10 +456,10 @@ def _move_class_casts(spec, mod, klass, error_log):
dst_klass.ctors.append(ctor)
-def _move_global_slot(spec, mod, global_slot, error_log):
+def _move_global_slot(spec, global_slot, error_log):
""" If possible, move a global slot to its correct class. """
- for overload in list(mod.overloads):
+ for overload in list(spec.module.overloads):
if overload.common is not global_slot:
continue
@@ -559,7 +554,7 @@ def _move_global_slot(spec, mod, global_slot, error_log):
proxy.members.insert(0, proxy_member)
# Remove the overload from the list.
- mod.overloads.remove(overload)
+ spec.module.overloads.remove(overload)
# Add the overload to the proxy.
overload.common = proxy_member
@@ -573,7 +568,7 @@ def _move_global_slot(spec, mod, global_slot, error_log):
continue
# Remove from the list.
- mod.overloads.remove(overload)
+ spec.module.overloads.remove(overload)
if arg_enum is not None:
_enum_iface_file_is_used(arg_enum, arg_module)
@@ -676,7 +671,7 @@ def _add_auto_overload(spec, auto_klass, auto_overload):
overload.is_autogenerated = False
klass.overloads.insert(0, overload)
- if _generating_code_for_module(spec, klass.iface_file.module):
+ if klass.iface_file.module is spec.module:
member.py_name.used = True
break
@@ -734,7 +729,7 @@ def _set_mro(spec, klass, error_log, seen=None):
if superklass_mro not in klass.mro:
klass.mro.append(superklass_mro)
- if _generating_code_for_module(spec, klass.iface_file.module):
+ if klass.iface_file.module is spec.module:
superklass_mro.iface_file.needed = True
if superklass_mro.deprecated:
@@ -767,7 +762,7 @@ def _set_mro(spec, klass, error_log, seen=None):
if klass.metatype is None and len(klass.superclasses) == 0:
klass.metatype = klass.iface_file.module.default_metatype
- if klass.metatype is not None and _generating_code_for_module(spec, klass.iface_file.module):
+ if klass.metatype is not None and klass.iface_file.module is spec.module:
klass.metatype.used = True
# If the class doesn't have an explicit super-type then inherit from
@@ -781,7 +776,7 @@ def _set_mro(spec, klass, error_log, seen=None):
if klass.supertype.name.endswith('sip.wrapper'):
klass.supertype = None
- if klass.supertype is not None and _generating_code_for_module(spec, klass.iface_file.module):
+ if klass.supertype is not None and klass.iface_file.module is spec.module:
klass.supertype.used = True
# Make sure that the module in which a sub-class convertor will be created
@@ -1005,7 +1000,7 @@ def _get_visible_py_members(spec, klass):
if overload.is_abstract:
klass.is_abstract = True
- if _generating_code_for_module(spec, klass.iface_file.module) and (klass is mro_klass or (overload.access_specifier is AccessSpecifier.PROTECTED and klass.has_shadow)):
+ if klass.iface_file.module is spec.module and (klass is mro_klass or (overload.access_specifier is AccessSpecifier.PROTECTED and klass.has_shadow)):
need_types = True
member.py_name.used = True
@@ -1072,7 +1067,7 @@ def _add_virtual_overload(spec, overload, klass, error_log):
# If this class is defined in the main module then make sure the virtuals
# have a handler.
- if _generating_code_for_module(spec, klass.iface_file.module):
+ if klass.iface_file.module is spec.module:
virtual_handler = _get_virtual_handler(spec, overload, klass,
error_log)
@@ -1081,7 +1076,7 @@ def _add_virtual_overload(spec, overload, klass, error_log):
# Make sure we have the interface files and type definitions for the
# virtual handler.
- _iface_files_are_used_by_overload(spec, spec.modules[0].used, overload,
+ _iface_files_are_used_by_overload(spec, spec.module.used, overload,
need_types=True)
else:
virtual_handler = None
@@ -1764,7 +1759,7 @@ def _resolve_type(spec, mod, scope, type, error_log, allow_defined=False):
# If we are in the main module then mark any generated types as being
# needed.
- if _generating_code_for_module(spec, mod):
+ if mod is spec.module:
_set_needed_type(type)
@@ -1780,7 +1775,7 @@ def _set_needed_type(arg):
def _set_needed_exceptions(spec, mod, throw_args):
""" Specify that a set of thrown arguments are needed. """
- if _generating_code_for_module(spec, mod) and throw_args is not None and throw_args.arguments is not None:
+ if mod is spec.module and throw_args is not None and throw_args.arguments is not None:
for exception in throw_args.arguments:
_set_needs_exception(exception)
@@ -1835,7 +1830,7 @@ def _instantiate_mapped_type_template(spec, mod, mapped_type_template, type,
mapped_type.type.is_reference = False
mapped_type.cpp_name = cached_name(spec, argument_as_str(mapped_type.type))
- if _generating_code_for_module(spec, mod):
+ if mod is spec.module:
mapped_type.cpp_name.used = True
proto_mapped_type = mapped_type_template.mapped_type
@@ -2114,7 +2109,7 @@ def _create_sorted_numbered_types(spec, mod, error_log):
if klass.iface_file.module is not mod:
continue
- if _generating_code_for_module(spec, mod) or klass.iface_file.needed:
+ if mod is spec.module or klass.iface_file.needed:
if not klass.is_hidden_namespace:
mod.needed_types.append(Argument(ArgumentType.CLASS,
definition=klass, name=klass.iface_file.cpp_name))
@@ -2123,7 +2118,7 @@ def _create_sorted_numbered_types(spec, mod, error_log):
if mapped_type.iface_file.module is not mod:
continue
- if _generating_code_for_module(spec, mod) or mapped_type.iface_file.needed:
+ if mod is spec.module or mapped_type.iface_file.needed:
mod.needed_types.append(Argument(ArgumentType.MAPPED,
definition=mapped_type, name=mapped_type.cpp_name))
@@ -2134,7 +2129,7 @@ def _create_sorted_numbered_types(spec, mod, error_log):
if enum.fq_cpp_name is None:
continue
- if _generating_code_for_module(spec, mod) or enum.needed:
+ if mod is spec.module or enum.needed:
mod.needed_types.append(Argument(ArgumentType.ENUM,
definition=enum, name=enum.cached_fq_cpp_name))
@@ -2164,14 +2159,6 @@ def _create_sorted_numbered_types(spec, mod, error_log):
needed_type_nr += 1
-def _generating_code_for_module(spec, mod):
- """ Return True if we are generating code for a module, ie. we are the main
- module.
- """
-
- return spec.modules[0] is mod
-
-
def _check_properties(klass, error_log):
""" Check that any properties are valid. """
diff --git a/sipbuild/generator/specification.py b/sipbuild/generator/specification.py
index 62f711d..eecaaab 100644
--- a/sipbuild/generator/specification.py
+++ b/sipbuild/generator/specification.py
@@ -1322,8 +1322,8 @@ class Specification:
# The mapped types.
mapped_types: List[MappedType] = field(default_factory=list)
- # The list of modules. Initially there is an unnamed module.
- modules: List[Module] = field(default_factory=lambda: [Module()])
+ # The module for which code is to be generated.
+ module: Module = field(default_factory=Module)
# The cache of names that may be required as strings in the generated code.
name_cache: Dict[int, List[CachedName]] = field(default_factory=dict)
diff --git a/sipbuild/module/source/12/sip.h.in b/sipbuild/module/source/12/sip.h.in
index 433acc0..fc7ff74 100644
--- a/sipbuild/module/source/12/sip.h.in
+++ b/sipbuild/module/source/12/sip.h.in
@@ -46,7 +46,7 @@ extern "C" {
/* The version of the ABI. */
#define SIP_ABI_MAJOR_VERSION 12
#define SIP_ABI_MINOR_VERSION 11
-#define SIP_MODULE_PATCH_VERSION 0
+#define SIP_MODULE_PATCH_VERSION 1
/*
diff --git a/sipbuild/module/source/12/siplib.c b/sipbuild/module/source/12/siplib.c
index 8bfb92a..e107698 100644
--- a/sipbuild/module/source/12/siplib.c
+++ b/sipbuild/module/source/12/siplib.c
@@ -12198,7 +12198,12 @@ static PyObject *sipEnumType_alloc(PyTypeObject *self, Py_ssize_t nitems)
sipEnumTypeObject *py_type;
sipPySlotDef *psd;
- assert(currentType != NULL);
+ if (currentType == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "enums cannot be sub-classed");
+ return NULL;
+ }
+
assert(sipTypeIsEnum(currentType));
/* Call the standard super-metatype alloc. */
diff --git a/sipbuild/module/source/13/sip.h.in b/sipbuild/module/source/13/sip.h.in
index 65867fa..7ed19b0 100644
--- a/sipbuild/module/source/13/sip.h.in
+++ b/sipbuild/module/source/13/sip.h.in
@@ -46,7 +46,7 @@ extern "C" {
/* The version of the ABI. */
#define SIP_ABI_MAJOR_VERSION 13
#define SIP_ABI_MINOR_VERSION 4
-#define SIP_MODULE_PATCH_VERSION 0
+#define SIP_MODULE_PATCH_VERSION 1
/*
diff --git a/sipbuild/module/source/13/sip_core.c b/sipbuild/module/source/13/sip_core.c
index 34c2948..c72f13a 100644
--- a/sipbuild/module/source/13/sip_core.c
+++ b/sipbuild/module/source/13/sip_core.c
@@ -4922,7 +4922,7 @@ static int parsePass2(PyObject *self, int selfarg, PyObject *sipArgs,
p = va_arg(va, void **);
if (flags & FMT_AP_TRANSFER)
- xfer = (isstatic ? arg : self);
+ xfer = ((isstatic || self == NULL) ? arg : self);
else if (flags & FMT_AP_TRANSFER_BACK)
xfer = Py_None;
else
diff --git a/sipbuild/version.py b/sipbuild/version.py
index ad361fa..4755178 100644
--- a/sipbuild/version.py
+++ b/sipbuild/version.py
@@ -1,2 +1,2 @@
-SIP_VERSION = 0x060705
-SIP_VERSION_STR = '6.7.5'
+SIP_VERSION = 0x060706
+SIP_VERSION_STR = '6.7.6'
More information about the Neon-commits
mailing list