Merge branch 'flatstaticmember'
* flatstaticmember: Test -flatstaticmethod and %extend Python -flatstaticmethod corrections Enable flat static constructor methods Move low level static methods Use flat static method if it's a "friend" Python: Option to generate flat class methods
This commit is contained in:
commit
9fd2356104
7 changed files with 67 additions and 34 deletions
|
|
@ -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)
|
Version 4.1.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2022-03-21: jschueller, jim-easterbrook, wsfulton
|
||||||
|
[Python] #2137 C++ static member functions no longer generate a "flattened"
|
||||||
|
name in the Python module. For example:
|
||||||
|
|
||||||
|
s = example.Spam()
|
||||||
|
s.foo() # Spam::foo() via an instance
|
||||||
|
example.Spam.foo() # Spam::foo() using class method
|
||||||
|
example.Spam_foo() # Spam::foo() "flattened" name
|
||||||
|
|
||||||
|
The "flattened" name is no longer generated, but can be generated
|
||||||
|
by using the new -flatstaticmethod option.
|
||||||
|
|
||||||
|
*** POTENTIAL INCOMPATIBILITY ***
|
||||||
|
|
||||||
2022-03-18: ianlancetaylor
|
2022-03-18: ianlancetaylor
|
||||||
[Go] #337 Implement %extend base methods in child classes.
|
[Go] #337 Implement %extend base methods in child classes.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -957,6 +957,7 @@ swig -python -help
|
||||||
<tr><td>-doxygen </td><td>Convert C++ doxygen comments to pydoc comments in proxy classes</td></tr>
|
<tr><td>-doxygen </td><td>Convert C++ doxygen comments to pydoc comments in proxy classes</td></tr>
|
||||||
<tr><td>-extranative </td><td>Return extra native wrappers for C++ std containers wherever possible</td></tr>
|
<tr><td>-extranative </td><td>Return extra native wrappers for C++ std containers wherever possible</td></tr>
|
||||||
<tr><td>-fastproxy </td><td>Use fast proxy mechanism for member methods</td></tr>
|
<tr><td>-fastproxy </td><td>Use fast proxy mechanism for member methods</td></tr>
|
||||||
|
<tr><td>-flatstaticmethod </td><td>Generate additional flattened Python methods for C++ static methods</td></tr>
|
||||||
<tr><td>-globals <name> </td><td>Set <name> used to access C global variable (default: 'cvar')</td></tr>
|
<tr><td>-globals <name> </td><td>Set <name> used to access C global variable (default: 'cvar')</td></tr>
|
||||||
<tr><td>-interface <mod></td><td>Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')</td></tr>
|
<tr><td>-interface <mod></td><td>Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')</td></tr>
|
||||||
<tr><td>-keyword </td><td>Use keyword arguments</td></tr>
|
<tr><td>-keyword </td><td>Use keyword arguments</td></tr>
|
||||||
|
|
@ -1616,16 +1617,17 @@ In Python, the static member can be accessed in three different ways:
|
||||||
|
|
||||||
<div class="targetlang">
|
<div class="targetlang">
|
||||||
<pre>
|
<pre>
|
||||||
>>> example.Spam_foo() # Spam::foo()
|
|
||||||
>>> s = example.Spam()
|
>>> s = example.Spam()
|
||||||
>>> s.foo() # Spam::foo() via an instance
|
>>> s.foo() # Spam::foo() via an instance
|
||||||
>>> example.Spam.foo() # Spam::foo() using Python-2.2 and later
|
>>> example.Spam.foo() # Spam::foo() using class method
|
||||||
|
>>> example.Spam_foo() # Spam::foo() "flattened" name
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The first two methods of access are supported in all versions of Python. The
|
The last technique is only available when using the <tt>-flatstaticmethod</tt> option.
|
||||||
last technique is only available in Python-2.2 and later versions.
|
This option is not recommended, it is only available for backwards compatibility
|
||||||
|
as ancient versions of Python did not have Python class methods.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ LIBS = -L.
|
||||||
VALGRIND_OPT += --suppressions=pythonswig.supp
|
VALGRIND_OPT += --suppressions=pythonswig.supp
|
||||||
|
|
||||||
# Custom tests - tests with additional commandline options
|
# Custom tests - tests with additional commandline options
|
||||||
#python_flatstaticmethod.cpptest: SWIGOPT += -flatstaticmethod
|
python_flatstaticmethod.cpptest: SWIGOPT += -flatstaticmethod
|
||||||
|
|
||||||
# Rules for the different types of tests
|
# Rules for the different types of tests
|
||||||
%.cpptest:
|
%.cpptest:
|
||||||
|
|
|
||||||
|
|
@ -63,12 +63,8 @@ check(inspect.getdoc(A.func3default),
|
||||||
|
|
||||||
check(inspect.getdoc(A.func0static),
|
check(inspect.getdoc(A.func0static),
|
||||||
"func0static(e, arg2, hello, f=2) -> int")
|
"func0static(e, arg2, hello, f=2) -> int")
|
||||||
check(inspect.getdoc(_autodoc.A_func0static),
|
|
||||||
"A_func0static(e, arg2, hello, f=2) -> int")
|
|
||||||
check(inspect.getdoc(A.func1static),
|
check(inspect.getdoc(A.func1static),
|
||||||
"func1static(A e, short arg2, Tuple hello, double f=2) -> int")
|
"func1static(A e, short arg2, Tuple hello, double f=2) -> int")
|
||||||
check(inspect.getdoc(_autodoc.A_func1static),
|
|
||||||
"A_func1static(A e, short arg2, Tuple hello, double f=2) -> int")
|
|
||||||
check(inspect.getdoc(A.func2static),
|
check(inspect.getdoc(A.func2static),
|
||||||
"func2static(e, arg2, hello, f=2) -> int\n"
|
"func2static(e, arg2, hello, f=2) -> int\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -78,15 +74,6 @@ check(inspect.getdoc(A.func2static),
|
||||||
"arg2: short\n"
|
"arg2: short\n"
|
||||||
"hello: int tuple[2]\n"
|
"hello: int tuple[2]\n"
|
||||||
"f: double")
|
"f: double")
|
||||||
check(inspect.getdoc(_autodoc.A_func2static),
|
|
||||||
"A_func2static(e, arg2, hello, f=2) -> int\n"
|
|
||||||
"\n"
|
|
||||||
"Parameters\n"
|
|
||||||
"----------\n"
|
|
||||||
"e: A *\n"
|
|
||||||
"arg2: short\n"
|
|
||||||
"hello: int tuple[2]\n"
|
|
||||||
"f: double")
|
|
||||||
check(inspect.getdoc(A.func3static),
|
check(inspect.getdoc(A.func3static),
|
||||||
"func3static(A e, short arg2, Tuple hello, double f=2) -> int\n"
|
"func3static(A e, short arg2, Tuple hello, double f=2) -> int\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -96,15 +83,6 @@ check(inspect.getdoc(A.func3static),
|
||||||
"arg2: short\n"
|
"arg2: short\n"
|
||||||
"hello: int tuple[2]\n"
|
"hello: int tuple[2]\n"
|
||||||
"f: double")
|
"f: double")
|
||||||
check(inspect.getdoc(_autodoc.A_func3static),
|
|
||||||
"A_func3static(A e, short arg2, Tuple hello, double f=2) -> int\n"
|
|
||||||
"\n"
|
|
||||||
"Parameters\n"
|
|
||||||
"----------\n"
|
|
||||||
"e: A *\n"
|
|
||||||
"arg2: short\n"
|
|
||||||
"hello: int tuple[2]\n"
|
|
||||||
"f: double")
|
|
||||||
|
|
||||||
check(inspect.getdoc(A.variable_a),
|
check(inspect.getdoc(A.variable_a),
|
||||||
"variable_a"
|
"variable_a"
|
||||||
|
|
@ -119,7 +97,7 @@ check(inspect.getdoc(A.variable_d),
|
||||||
"variable_d : int"
|
"variable_d : int"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the low-level functions (not present when using -builtin except for the static ones)
|
# Check the low-level functions (not present when using -builtin)
|
||||||
if not is_python_builtin():
|
if not is_python_builtin():
|
||||||
check(inspect.getdoc(_autodoc.A_funk), "just a string.")
|
check(inspect.getdoc(_autodoc.A_funk), "just a string.")
|
||||||
check(inspect.getdoc(_autodoc.A_func0),
|
check(inspect.getdoc(_autodoc.A_func0),
|
||||||
|
|
@ -162,6 +140,28 @@ if not is_python_builtin():
|
||||||
"arg3: short\n"
|
"arg3: short\n"
|
||||||
"hello: int tuple[2]\n"
|
"hello: int tuple[2]\n"
|
||||||
"f: double")
|
"f: double")
|
||||||
|
check(inspect.getdoc(_autodoc.A_func0static),
|
||||||
|
"A_func0static(e, arg2, hello, f=2) -> int")
|
||||||
|
check(inspect.getdoc(_autodoc.A_func1static),
|
||||||
|
"A_func1static(A e, short arg2, Tuple hello, double f=2) -> int")
|
||||||
|
check(inspect.getdoc(_autodoc.A_func2static),
|
||||||
|
"A_func2static(e, arg2, hello, f=2) -> int\n"
|
||||||
|
"\n"
|
||||||
|
"Parameters\n"
|
||||||
|
"----------\n"
|
||||||
|
"e: A *\n"
|
||||||
|
"arg2: short\n"
|
||||||
|
"hello: int tuple[2]\n"
|
||||||
|
"f: double")
|
||||||
|
check(inspect.getdoc(_autodoc.A_func3static),
|
||||||
|
"A_func3static(A e, short arg2, Tuple hello, double f=2) -> int\n"
|
||||||
|
"\n"
|
||||||
|
"Parameters\n"
|
||||||
|
"----------\n"
|
||||||
|
"e: A *\n"
|
||||||
|
"arg2: short\n"
|
||||||
|
"hello: int tuple[2]\n"
|
||||||
|
"f: double")
|
||||||
check(inspect.getdoc(_autodoc.A_variable_a_set), "A_variable_a_set(self, variable_a)")
|
check(inspect.getdoc(_autodoc.A_variable_a_set), "A_variable_a_set(self, variable_a)")
|
||||||
check(inspect.getdoc(_autodoc.A_variable_a_get), "A_variable_a_get(self) -> int" )
|
check(inspect.getdoc(_autodoc.A_variable_a_get), "A_variable_a_get(self) -> int" )
|
||||||
check(inspect.getdoc(_autodoc.A_variable_b_set), "A_variable_b_set(A self, int variable_b)")
|
check(inspect.getdoc(_autodoc.A_variable_b_set), "A_variable_b_set(A self, int variable_b)")
|
||||||
|
|
|
||||||
|
|
@ -83,3 +83,10 @@ if A.defargs(1) != 21:
|
||||||
|
|
||||||
if A.defargs(1, 2) != 3:
|
if A.defargs(1, 2) != 3:
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
|
# %extend
|
||||||
|
if A_staticextended(11) != 11:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
if A.staticextended(11) != 11:
|
||||||
|
raise RuntimeError
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@
|
||||||
%typemap(in) (int c, int d) "$1 = 0; $2 = 0;";
|
%typemap(in) (int c, int d) "$1 = 0; $2 = 0;";
|
||||||
%typemap(doc,name="hello",type="Tuple") (int c, int d) "hello: int tuple[2]";
|
%typemap(doc,name="hello",type="Tuple") (int c, int d) "hello: int tuple[2]";
|
||||||
|
|
||||||
|
%extend A {
|
||||||
|
static int staticextended(int i) { return i; }
|
||||||
|
}
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
struct A {
|
struct A {
|
||||||
static int bar(int a) {
|
static int bar(int a) {
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ static int castmode = 0;
|
||||||
static int extranative = 0;
|
static int extranative = 0;
|
||||||
static int nortti = 0;
|
static int nortti = 0;
|
||||||
static int relativeimport = 0;
|
static int relativeimport = 0;
|
||||||
|
static int flat_static_method = 0;
|
||||||
|
|
||||||
/* flags for the make_autodoc function */
|
/* flags for the make_autodoc function */
|
||||||
namespace {
|
namespace {
|
||||||
|
|
@ -118,6 +119,7 @@ Python Options (available with -python)\n\
|
||||||
-doxygen - Convert C++ doxygen comments to pydoc comments in proxy classes\n\
|
-doxygen - Convert C++ doxygen comments to pydoc comments in proxy classes\n\
|
||||||
-extranative - Return extra native wrappers for C++ std containers wherever possible\n\
|
-extranative - Return extra native wrappers for C++ std containers wherever possible\n\
|
||||||
-fastproxy - Use fast proxy mechanism for member methods\n\
|
-fastproxy - Use fast proxy mechanism for member methods\n\
|
||||||
|
-flatstaticmethod - Generate additional flattened Python methods for C++ static methods\n\
|
||||||
-globals <name> - Set <name> used to access C global variable (default: 'cvar')\n\
|
-globals <name> - Set <name> used to access C global variable (default: 'cvar')\n\
|
||||||
-interface <mod>- Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')\n\
|
-interface <mod>- Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')\n\
|
||||||
-keyword - Use keyword arguments\n";
|
-keyword - Use keyword arguments\n";
|
||||||
|
|
@ -373,6 +375,9 @@ public:
|
||||||
} else if (strcmp(argv[i], "-extranative") == 0) {
|
} else if (strcmp(argv[i], "-extranative") == 0) {
|
||||||
extranative = 1;
|
extranative = 1;
|
||||||
Swig_mark_arg(i);
|
Swig_mark_arg(i);
|
||||||
|
} else if (strcmp(argv[i], "-flatstaticmethod") == 0) {
|
||||||
|
flat_static_method = 1;
|
||||||
|
Swig_mark_arg(i);
|
||||||
} else if (strcmp(argv[i], "-noh") == 0) {
|
} else if (strcmp(argv[i], "-noh") == 0) {
|
||||||
no_header_file = 1;
|
no_header_file = 1;
|
||||||
Swig_mark_arg(i);
|
Swig_mark_arg(i);
|
||||||
|
|
@ -2532,7 +2537,7 @@ public:
|
||||||
/* ------------------------------------------------------------
|
/* ------------------------------------------------------------
|
||||||
* dispatchFunction()
|
* dispatchFunction()
|
||||||
* ------------------------------------------------------------ */
|
* ------------------------------------------------------------ */
|
||||||
void dispatchFunction(Node *n, String *linkage, int funpack = 0, bool builtin_self = false, bool builtin_ctor = false, bool director_class = false) {
|
void dispatchFunction(Node *n, String *linkage, int funpack = 0, bool builtin_self = false, bool builtin_ctor = false, bool director_class = false, bool use_static_method = false) {
|
||||||
/* Last node in overloaded chain */
|
/* Last node in overloaded chain */
|
||||||
|
|
||||||
bool add_self = builtin_self && (!builtin_ctor || director_class);
|
bool add_self = builtin_self && (!builtin_ctor || director_class);
|
||||||
|
|
@ -2636,11 +2641,11 @@ public:
|
||||||
Printv(f->code, "}\n", NIL);
|
Printv(f->code, "}\n", NIL);
|
||||||
Wrapper_print(f, f_wrappers);
|
Wrapper_print(f, f_wrappers);
|
||||||
Node *p = Getattr(n, "sym:previousSibling");
|
Node *p = Getattr(n, "sym:previousSibling");
|
||||||
if (!builtin_self)
|
if (!builtin_self && (use_static_method || !builtin))
|
||||||
add_method(symname, wname, 0, p);
|
add_method(symname, wname, 0, p);
|
||||||
|
|
||||||
/* Create a shadow for this function (if enabled and not in a member function) */
|
/* Create a shadow for this function (if enabled and not in a member function) */
|
||||||
if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) {
|
if (!builtin && shadow && (!(shadow & PYSHADOW_MEMBER)) && use_static_method) {
|
||||||
emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, symname, 0);
|
emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, symname, 0);
|
||||||
}
|
}
|
||||||
DelWrapper(f);
|
DelWrapper(f);
|
||||||
|
|
@ -3307,18 +3312,19 @@ public:
|
||||||
Wrapper_print(f, f_wrappers);
|
Wrapper_print(f, f_wrappers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool use_static_method = flat_static_method || !Swig_storage_isstatic_custom(n, "staticmemberfunctionHandler:storage");
|
||||||
/* Now register the function with the interpreter. */
|
/* Now register the function with the interpreter. */
|
||||||
if (!Getattr(n, "sym:overloaded")) {
|
if (!Getattr(n, "sym:overloaded")) {
|
||||||
if (!builtin_self)
|
if (!builtin_self && (use_static_method || !builtin))
|
||||||
add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments);
|
add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments);
|
||||||
|
|
||||||
/* Create a shadow for this function (if enabled and not in a member function) */
|
/* Create a shadow for this function (if enabled and not in a member function) */
|
||||||
if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) {
|
if (!builtin && shadow && (!(shadow & PYSHADOW_MEMBER)) && use_static_method) {
|
||||||
emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs);
|
emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!Getattr(n, "sym:nextSibling")) {
|
if (!Getattr(n, "sym:nextSibling")) {
|
||||||
dispatchFunction(n, linkage, funpack, builtin_self, builtin_ctor, director_class);
|
dispatchFunction(n, linkage, funpack, builtin_self, builtin_ctor, director_class, use_static_method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue