From 2072ae19c91cc2b3888e40e5a63b856473c9129e Mon Sep 17 00:00:00 2001
From: William S Fulton
Date: Sun, 27 Feb 2022 10:06:45 +0000
Subject: [PATCH] Python function annotations removed from -py3 option.
Python function annotations containing C/C++ types are no longer
generated when using the -py3 option. Function annotations support
has been moved to a feature to provide finer grained control.
It can be turned on globally by adding:
%feature("python:annotations", "c");
or by using the command line argument:
-features python:annotations=c
The implementation is designed to be expandable to support different
annotations implementations. Future implementations could implement
something like the following for generating pure Python types:
%feature("python:annotations", "python");
or typing module types to conform to PEP-484:
%feature("python:annotations", "typing");
Closes #1561
Issue #735
---
CHANGES.current | 14 +++
Doc/Manual/Contents.html | 5 +-
Doc/Manual/Python.html | 86 +++++++++++++------
Examples/test-suite/python/Makefile.in | 1 +
.../python/python_annotations_c_runme.py | 27 ++++++
Examples/test-suite/python_annotations_c.i | 26 ++++++
Source/Modules/python.cxx | 7 +-
7 files changed, 133 insertions(+), 33 deletions(-)
create mode 100644 Examples/test-suite/python/python_annotations_c_runme.py
create mode 100644 Examples/test-suite/python_annotations_c.i
diff --git a/CHANGES.current b/CHANGES.current
index 2563749a2..1dc7709da 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,20 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
+2022-02-27: wsfulton
+ [Python] #735 #1561 Function annotations containing C/C++ types are no longer
+ generated when using the -py3 option. Function annotations support has been
+ moved to a feature to provide finer grained control. It can be turned on
+ globally by adding:
+
+ %feature("python:annotations", "c");
+
+ or by using the command line argument:
+
+ -features python:annotations=c
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
2022-02-26: wsfulton
#655 #1840 Add new warning WARN_LANG_USING_NAME_DIFFERENT to warn when a
method introduced by a using declaration in a derived class cannot
diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html
index b1da2953a..433ae5f9e 100644
--- a/Doc/Manual/Contents.html
+++ b/Doc/Manual/Contents.html
@@ -1478,7 +1478,10 @@
Python 3 Support
Python 3 Support
-
+
-The -py3 option will enable function annotation support. When used
-SWIG is able to generate proxy method definitions like this:
-
-
-
- def foo(self, bar : "int"=0) -> "void" : ...
-
-
-
-Also, even if without passing SWIG the -py3 option, the parameter list
-still could be generated:
-
-
-
- def foo(self, bar=0): ...
-
-
-
-But for overloaded function or method, the parameter list would fallback to
-*args or self, *args, and **kwargs may be append
-depend on whether you enabled the keyword argument. This fallback is due to
-all overloaded functions share the same function in SWIG generated proxy class.
-
-
-
-For detailed usage of function annotation, see
+Python 3 supports function annotations as defined in
PEP 3107.
+Annotation support is via a python:annotations
+%feature directives.
+SWIG currently supports one type of function annotation.
+
+
+
+
+
+
+The %feature("python:annotations", "c") directive generates function annotations
+containing C/C++ types. For example:
+
+
+
+%feature("python:annotations", "c") global_ints;
+int *global_ints(int &ri);
+
+
+
+The generated code then contains function annotations containing the C types:
+
+
+
+def global_ints(ri: "int &") -> "int *":
+ return _python_annotations_c.global_ints(ri)
+
+
+
+There are some limitations with annotations support, for example, overloaded functions use
+*args or **kwargs when keyword arguments are enabled.
+The parameter names and types are then not shown. For example, with input:
+
+
+
+int *global_overloaded(int &ri);
+int *global_overloaded();
+
+
+
+The generated Python function including annotations is shown below.
+Only the return type is annotated.
+
+
+
+def global_overloaded(*args) -> "int *":
+ return _python_annotations_c.global_overloaded(*args)
+
+
+
+Compatibility Note: SWIG-4.1.0 changed the way that function annotations are generated.
+Prior versions required the -py3 option which enabled function annotation support
+containing C/C++ types instead of supporting %feature("python:annotations", "c").
diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in
index c10d9abf7..57f72d512 100644
--- a/Examples/test-suite/python/Makefile.in
+++ b/Examples/test-suite/python/Makefile.in
@@ -48,6 +48,7 @@ CPP_TEST_CASES += \
li_std_wstring_inherit \
primitive_types \
python_abstractbase \
+ python_annotations_c \
python_append \
python_builtin \
python_destructor_exception \
diff --git a/Examples/test-suite/python/python_annotations_c_runme.py b/Examples/test-suite/python/python_annotations_c_runme.py
new file mode 100644
index 000000000..8a4671aa0
--- /dev/null
+++ b/Examples/test-suite/python/python_annotations_c_runme.py
@@ -0,0 +1,27 @@
+import sys
+
+if sys.version_info[0:2] >= (3, 2):
+ from python_annotations_c import *
+
+ anno = MakeShort.__annotations__
+ if anno != {'x': 'int', 'return': 'Space::Template< short >'}:
+ raise RuntimeError("annotations mismatch: {}".format(anno))
+
+ anno = global_ints.__annotations__
+ if anno != {'ri': 'int &', 't': 'TemplateShort', 'return': 'int *'}:
+ raise RuntimeError("annotations mismatch: {}".format(anno))
+
+ ts = MakeShort(10)
+
+ anno = MakeShort.__annotations__
+ if anno != {'x': 'int', 'return': 'Space::Template< short >'}:
+ raise RuntimeError("annotations mismatch: {}".format(anno))
+
+ anno = ts.mymethod.__annotations__
+ if anno != {'arg2': 'int', 'tt': 'TemplateShort', 'return': 'void'}:
+ raise RuntimeError("annotations mismatch: {}".format(anno))
+
+ # No annotations
+ anno = no_annotations.__annotations__
+ if anno != {}:
+ raise RuntimeError("annotations mismatch: {}".format(anno))
diff --git a/Examples/test-suite/python_annotations_c.i b/Examples/test-suite/python_annotations_c.i
new file mode 100644
index 000000000..dc590d6f5
--- /dev/null
+++ b/Examples/test-suite/python_annotations_c.i
@@ -0,0 +1,26 @@
+%module python_annotations_c
+
+// Tests the C/C++ annotations that were automatically added by using -py3 before swig-4.1.0
+// In swig-4.1.0 and later, the feature below is needed as annotations are no longer generated with -py3
+%feature("python:annotations", "c") mymethod;
+%feature("python:annotations", "c") makeT;
+%feature("python:annotations", "c") global_ints;
+
+%inline %{
+namespace Space {
+template
+struct Template {
+ void mymethod(int, Template* tt) {}
+};
+}
+template
+Space::Template makeT(int x) {
+ return Space::Template();
+};
+int *global_ints(int &ri, Space::Template t) { return &ri; }
+int *global_overloaded(int &ri) { return &ri; }
+int *global_overloaded() { return NULL; }
+int *no_annotations(int &ri, const char *c) { return NULL; }
+%}
+%template(TemplateShort) Space::Template;
+%template(MakeShort) makeT;
diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
index 0845c8f9c..8c537a527 100644
--- a/Source/Modules/python.cxx
+++ b/Source/Modules/python.cxx
@@ -316,7 +316,6 @@ public:
} else {
Swig_arg_error();
}
- /* end added */
} else if (strcmp(argv[i], "-globals") == 0) {
if (argv[i + 1]) {
global_name = NewString(argv[i + 1]);
@@ -2275,7 +2274,7 @@ public:
return parms;
}
- bool funcanno = py3 ? true : false;
+ bool funcanno = Equal(Getattr(n, "feature:python:annotations"), "c") ? true : false;
String *params = NewString("");
String *_params = make_autodocParmList(n, false, ((in_class || has_self_for_count)? 2 : 1), is_calling, funcanno);
@@ -2391,8 +2390,8 @@ public:
if (ret)
ret = SwigType_str(ret, 0);
}
- return (ret && py3) ? NewStringf(" -> \"%s\"", ret)
- : NewString("");
+ bool funcanno = Equal(Getattr(n, "feature:python:annotations"), "c") ? true : false;
+ return (ret && funcanno) ? NewStringf(" -> \"%s\"", ret) : NewString("");
}
/* ------------------------------------------------------------