Commit Graph

181 Commits

Author SHA1 Message Date
William S Fulton f06d86749c [Python] Fix empty classes and imported bases in .pyi files
A generated stub class with no wrapped members had an empty suite, which
is invalid Python syntax. Stubs could also refer to base classes from
%imported modules without importing the corresponding Python proxy
module, leaving those names unresolved.

Track whether each stub class emits a member and use an ellipsis when
its body would otherwise be empty. Collect modules referenced through
%import and emit them before declarations, using the same package and
relative import rules as the generated Python proxy.

Keep annotation tests active with -pyi by parsing annotations from the
generated stub instead of expecting them on runtime objects. Include
each generated .pyi file in multi-module Pyrefly checks.

Add Python 3.14 Linux CI configurations for -pyi -typehints with and
without -builtin.

See #3473.

Assisted-by: Codex (GPT-5.6 Sol)
2026-08-04 23:41:57 +01:00
William S Fulton b9cbc4e624 [Python] Clean all generated stub files
Remove generated .pyi files alongside Python proxy files during
test-suite and example cleanup. Use .py* patterns so stubs produced
with SWIG_FEATURES=-pyi and other Python sidecar files are covered by
the existing clean rules.
2026-08-04 23:41:57 +01:00
William S Fulton ff961037ea [Python] Add -typehints and Pyrefly checks
Add -typehints to enable PEP 484 annotations for a whole interface.
Run Pyrefly on generated wrappers in the Python examples and test suite
with SWIG_FEATURES=-typehints.

Keep C/C++ annotation tests in their original mode, and add a Python
3.14 Linux CI build that runs with -typehints.

See #735.

Assisted-by: Codex (GPT-5.6 Sol)
2026-08-04 23:41:57 +01:00
William S Fulton 7c4215cb56 [Python] Director PyObject * typemap fixes and test tidy up
Follow on fixes to the previous commit:

Use SWIG_Py_XINCREF instead of Py_INCREF. Py_INCREF crashes on a null
PyObject * argument, which a C++ caller may legitimately pass, turning
what was a recoverable director error into a segfault. SWIG_Py_XINCREF
also honours the stable ABI, where it expands to Py_IncRef, and matches
the macros used elsewhere in pyclasses.swg.

Declare the typemap before the %apply directives in pyclasses.swg. %apply
copies the typemaps that exist at the point it appears, so a directorin
typemap declared after them was never propagated to swig::SwigPtr_PyObject
or swig::SwigVar_PyObject, which suffered from the same underflow. Passing
a swig::SwigPtr_PyObject by value was worse, as the wrapper variable stole
the reference held by the argument.

Rename the test to python_director_pyobject following the naming used for
the other Python only tests, and extend it to cover swig::SwigPtr_PyObject,
swig::SwigVar_PyObject and a null argument. Remove the unused variable and
the no-op if from the runme file, check the reference count after the
garbage collection loop and drop the success message, as the tests are
silent when they pass.

Add the CHANGES.current entry.

Assisted-by: Claude Code (Opus 5)
2026-08-01 15:11:22 +01:00
Julien Schueller 495723408e [Python] Fix refcount underflow in director
Each director upcall for a method taking PyObject* created a
SwigVar_PyObject, assigned the C++ parameter (a borrowed reference)
to it, then let the SwigVar_PyObject destructor DECREF it on scope
exit -- with no matching INCREF.  After enough calls the object's
reference count underflowed, the object was freed prematurely, and
the next call crashed with 'deletion of interned string failed'.

Fix: add a %typemap(directorin,noblock=1) for PyObject* that INCREFs
the parameter after assignment, balancing the destructor's DECREF.

Fixes #2015.

Assisted-by: opencode (deepseek-v4-flash)
2026-08-01 14:21:22 +01:00
William S Fulton 43ca691f0f [Python] Fix -pyi stub generation, rename option, add docs and test
Fixes and finishes off the -pyi-stub feature (generates a .pyi PEP 484
stub file alongside the wrapped module):

- printClassHeader() called _swig_add_metaclass, a runtime helper that
  no longer exists, which would raise a NameError for any class using
  %feature("python:nondynamic"). Switched to the current metaclass=
  keyword-argument approach used elsewhere in this file.

- classHandler() called addSymbol() unconditionally, so plain -noproxy
  builds (unrelated to -pyi) could fail with spurious "multiply
  defined" errors. Gated back to (shadow || pyi_stub).

- The opaque SWIGTYPE_* wrapper classes are now emitted into the .pyi
  stub too, not just the .py file, so $pytypename annotations falling
  back to an opaque type resolve to a name actually defined in the stub.

- Unannotated variables/constants were emitted into the .pyi as a bare
  name with nothing else on the line, which is not a valid attribute
  declaration. Falls back to ": typing.Any".

- Regular instance methods and static methods were both silently
  missing from the .pyi under -builtin (the option's primary intended
  use case), because two separate code paths never reached the shared
  pyi_stub emission logic.

- Renamed the command line option from -pyi-stub to -pyi, and improved
  the -help text with the PYI ("Python Interface") acronym.

- Added header comment blocks to the new helper methods, matching the
  file's existing convention.

- Documented -pyi in the manual with a worked, verified example, and
  marked the pytyping/-pyi work as experimental/still evolving in
  CHANGES.current.

- Added a python test-suite case (python_pyi.i) built with -builtin
  -pyi, covering a constructor, regular method, static method, member
  variable and an opaque-type fallback in one go. Clean up generated
  .pyi files in the Makefiles the same way .py files already are.

Assisted-by: Claude Code (Sonnet 5)
2026-07-29 18:58:46 +01:00
William S Fulton a0da96aff8 [Python] #3390 Add $pytypename special variable for pytyping typemaps
Finalises the PR keeping the $pytypename mechanism but leaving the default
pytyping SWIGTYPE typemaps as typing.Any. The special variables are exercised
only through explicit typemaps; the default annotation change and the
library-wide pytyping sweep are left for a follow-up.

python.cxx:
- getProxyClassLocalName() uses import_name_string() so a class from an
  imported module gets its fully qualified, package-aware name, as in
  classDeclaration().
- Guard substitutePytypingVars() against a null typemap and skip work when
  there is no special variable to substitute.
- Error when $*pytypename is applied to a non-pointer type instead of
  emitting the literal.
- Remove the _swig_python_version_info >= (3, 5) guards; SWIG supports Python
  3.5 and later, so import typing unconditionally and use a bare
  if typing.TYPE_CHECKING.
- Fix two leaks (SwigType_manglestr, SwigType_typedef_resolve_all).

Doc/Manual/Python.html: correct the feature value pytyping to typing and
document the new special variables with valid HTML.

Tests: python_annotations_typing opts in to proxy-name annotations via explicit
typemaps and covers $*pytypename, class-typed member variables, a class-typed
%constant, and the opaque fallback for a forward-declared class; add
python_annotations_import for the cross-module module-qualified name.

Assisted-by: Claude Code (Opus 4.8)
2026-07-27 23:40:48 +01:00
Julien Schueller c3983ffabb [Python] Fix metaclass conflict under -builtin
The SwigPyObjectType metaclass and SwigPyStaticVar type created via
PyType_FromSpec in the heap types path of builtin.swg were allocated as
distinct heap type instances in each compiled module's copy of the
TypeOnce functions. When a class inherited from types defined in
different SWIG extension modules -- such as a director class from
module A and a non-director class from module B -- PyType_FromSpecWithBases
detected incompatible metaclasses and raised:

  TypeError: metaclass conflict

Both TypeOnce functions now check the shared runtime data module for an
existing instance before creating a new one, so all modules share a
single metaclass. This regression was introduced when SWIG_HEAPTYPES
was enabled by default (SWIG 4.4) and only manifests on Python 3.12+.

Fixes #3315.

Assisted-by: opencode (deepseek-v4-flash)
2026-07-22 16:54:04 +02:00
Julien Schueller a1c738f02f Python: Drop python2 build 2026-07-06 23:50:30 +01:00
William S Fulton 349addecbc [Python] Fix %nokwargs being ignored under -keyword
%nokwargs (and %feature("kwargs", "0")) on an individual function was
silently ignored when the -keyword command line option was set, because
check_kwargs() used GetFlag() which cannot distinguish "feature unset"
from feature value "0". Honour the explicit feature value when set
instead of OR-ing it with use_kw.

Visible under -builtin where the affected function's wrapper now uses
METH_VARARGS instead of METH_VARARGS|METH_KEYWORDS, so calling with
kwargs raises TypeError as expected. Without -builtin, the generated
Python proxy accepts named arguments and forwards them positionally,
masking the C wrapper level rejection - the runmes therefore gate the
TypeError assertions on is_python_builtin().

Add regression test python_nokwargs_keyword (built with -keyword) that
fails on the unfixed code, plus a parallel python_nokwargs_feature that
exercises the same opt-out behaviour via a module-wide %feature("kwargs").
Both cover constructors, instance methods, static methods, and global
functions.

Assisted-by: Claude Opus 4.7
2026-05-25 16:16:17 +01:00
William S Fulton 4433e444b8 shared_ptr tests cleanup
- Add changes entry for new Lua shared_ptr support.
- Rename director_smartptr test to director_shared_ptr.
- Reimplement cpp11_shared_ptr test cases so that they are run by all
  languages (in common.mk instead of being in chosen language's Makefile.in files).
  This makes sure missing tests are run by all languages that support
  shared_ptr.
2026-03-26 08:37:18 +00:00
Nerixyz 5c35726a8d
Python: Add PEP 484 annotations for simple types 2026-03-24 14:56:16 +01:00
Seth Junot 195018f0dc Fix descriptor() type lookup when SwigPyIterator is renamed via #define
The hardcoded string literal "swig::SwigPyIterator *" in descriptor() is
not expanded for per-module renames of SwigPyIterator. The change allows
the new name(s) to be passed into SWIG_TypeQuery().

A similar issue is described in #3189.

Add test for SwigPyIterator descriptor() with per-module rename

Closes #3365
2026-03-10 22:07:31 +00:00
William S Fulton 5275850028 Try replicate issue described in #3337 2026-02-20 19:35:40 +00:00
William S Fulton 5ead577916 Restore missing testing of python_pybuffer testcase
Previous commit stopped testing this testcase when Py_LIMITED_API < 3.11.

Add changes file entry for Py_LIMITED_API bug fix in previous few commits.
2025-12-04 06:42:02 +00:00
Julien Schueller 208afd536b CI: Add py3.13/abi3.9 2025-12-04 06:41:07 +00:00
Jim Easterbrook 3a37288e06 Merge branch 'master' into fix_1792 2025-07-19 09:53:34 +01:00
crusaderky 6b556a6a1c Add -nogil opt-in flag to remove need for PYTHON_GIL=0
Closes #3215
2025-07-18 22:41:36 +01:00
Jim Easterbrook 20da01780f Enable Python builtin heap types buffer interface (#3219)
For Python < 3.9 the tp_as_buffer member is set explicitly if the
interface has a bf_getbuffer slot defined. This fixes #3211.

Enabled buffer interface for non-builtin test.
This only works with Python >= 3.12, where methods __buffer__ and
__release_buffer__ were added. Unfortunately it's not practical for
these methods to reuse the slot methods (or vice versa).

Disable Py_LIMITED_API if below 3.11. The Py_buffer struct and
associated functions are not defined in earlier stable API versions.

Closes #3211
2025-07-18 07:43:34 +01:00
Jim Easterbrook 976205ef0d Python: add weakref support to builtin types
These changes add a weakreflist member to SwigPyObject, and set
tp_weaklistoffset to its offset. This fixes #1792.

The Py_TPFLAGS_MANAGED_WEAKREF introduced in Python 3.12 requires
Py_TPFLAGS_HAVE_GC to be set as well, which it currently isn't for
SwigPyObjectType. (See https://github.com/python/cpython/issues/134786).
2025-07-10 08:11:38 +01:00
William S Fulton af6120329c Replace use of tp_name in builtin wrappers for Py_LIMITED_API support
Add SWIG_PyType_GetFullyQualifiedName which is just a wrapper around
PyType_GetFullyQualifiedName, but is only available in python-3.13.
Code up the equivalent for earlier versions - loosely based on the
python-3.13 implementation.

PyType_GetFullyQualifiedName is recommended in PEP-737 for getting the
fully qualified type name of a type.
2025-07-09 19:19:01 +01:00
William S Fulton f3672e2d6f Py_LIMITED_API support in SwigPyObject_Check for -builtin
Simplify implementation for -builtin, which does not need a fallback to
use strcmp as PyType_IsSubtype() 'just works' even when using multiple
modules (I think perhaps because SwigPyObject_stype->clientdata->pytype is
common across modules due to the implementation in SwigPyObject_Type()).

In the non-builtin case SwigPyObject is not a base type and usage is
different and when multiple modules are being used, SwigPyObject_Type()
returns two implementations of SwigPyObject which is solved in a hacky
way by comparing the types as strings when the pointer comparison fails.

Add import_callback test - tests %import and %callback to exercise
all of SwigPyPacked_Check(). Python only - the main callback example is
not widely tested and needs work in most of the other languages.
2025-06-09 18:36:13 +01:00
William S Fulton 9156ecc669 Add -Walways when running Python interpreter to find more warnings
I tried with -Werror but observed the warning messages disappearing
and tests not failing - probably because the wrapper code is swallowing
warnings and catching the resulting error. Seen in python_overload_simple_cast_runme.py
on Linux (not Windows!). Also when the warning is turned into an error
just a seg fault can occur without the warning message. All round better
to actually see the warning.
2025-05-13 21:49:37 +01:00
William S Fulton 24de76daeb Update/fix hugemod test case to work again 2025-04-20 15:27:28 +01:00
William S Fulton 1b09f4f111 Refactor python no-gil detection
Also additional python interpreter flags cleanup, use PYFLAGS consistently and remove PYTHONFLAGS.
2025-04-17 17:44:02 +01:00
Olly Betts 0b4496a735 Fix testsuite SWIG warnings; enable SWIG -Werror
SWIG/mzscheme (aka racket) is excluded for now as it currently has a lot
of testsuite warnings and is slated for removal in 4.4.0 anyway.

Closes #3034
2024-10-22 10:30:52 +13:00
William S Fulton 60a476982a Run inout testcase for all languages except D 2024-10-05 23:29:34 +01:00
Erez Geva 3dfd65e1cd Add test to director guard using multiple threads.
Signed-off-by: Erez Geva <ErezGeva2@gmail.com>

Issue #2949
2024-07-12 18:54:10 +01:00
William S Fulton 86e5e8d5e2 Don't run abi3audit on builtin test 2024-03-25 07:52:50 +00:00
William S Fulton 3be670e8db Fix assertion handling upcasting when using %shared_ptr on some templates.
A different approach is taken for supporting casting smart pointers up the
inheritance hierarchy. We no longer try to replace the underlying pointer type,
provided in the 'feature:smartptr', with the base class type. Such as morphing
'std::shared_ptr<(Derived)>' into 'std::shared_ptr<(Base)>'. Instead, we simply
use 'feature:smartptr' from the base class. This is more reliable than trying to
pattern match the pointer type in the feature. The base class must of course
also have the 'feature:smartptr' set, and this is still checked for as before.
The feature is now parsed in one place and stored in the parse tree in the
new 'smart' attribute for handling by the target languages.

Fix also improves the handling of the type parsed in 'feature:smartptr' in that
the type is now normalized and resolved in the scope of the class it is attached
to.

Closes #2768
2024-01-30 22:24:42 +00:00
William S Fulton faf1e17b45 Merge branch 'std_filesystem_python'
* std_filesystem_python:
  Add <type_traits> fragment for traits usage in std::filesystem
  Correct const std::filesystem & typemaps
  Fix memory leak wrapping const std::filesystem&
  std::filesystem pointer handling correction
  Python std::filesystem cleanup
  Cosmetic whitespace corrections
  Try to use wstring/wchar_t on windows
  Reformat
  Rename the helpers within the fragment to be more uniquely named
  Make CI rerun (and output all failed cases for the specialPath)
  Address review comments
  Need to see which assert is failing on mingw
  Verbose assert to try and see the failure on mingw
  path::string() returns a copy not a const ref.
  Remove cpp17_std_filesystem from common.mk, only defined for Python for now
  Extend roundtrip test
  Address review comment by @degasus on #1999 originally
  Had trouble getting the test to be properly ignored. If I wrap the inline line 35 in #if __cplusplus the wrapper code isn't generated
  Tweak tests setup
  Cherry pick from yasamoka/master

Conflicts:
	CHANGES.current
2023-11-18 10:50:29 +00:00
William S Fulton 68b0fd809f $typemap() fix for handling variable overrides
Fix when variable override contains a pointer dereference ->.
This enables use of $1.x as a variable override value as SWIG
replaces $1.x with a pointer dereference expression, such as
(&arg1)->x.

Added a testcase showing how Python typemaps could alternatively
be written using $typemap() instead of using C++ templates as used in
the UTL. I'm not convinced this is fully reliable or even a good idea,
so the variable replacements in $typemap() remain undocumented.
2023-11-03 09:07:51 +00:00
Christophe Calmejane e62945e273 Added unit test 2023-07-04 10:31:13 +02:00
Ramzi Sabra 2fcbd937f7
Cherry pick from yasamoka/master
Co-authored-by: Julien Marrec <julien.marrec@gmail.com>
2023-06-30 14:11:14 +02:00
Olly Betts 29d1f95d0d [Python] Add string_view support
Only implemented for Python 3, at least for now.

See #1567
2023-05-26 17:45:24 +12:00
William S Fulton 1835580589 Remove undocumented and non-existent STL std::carray 2023-04-26 18:18:15 +01:00
Olly Betts 07f0b732ba Add machinery for C++14, C++17 and C++20 testing
Support running testcases conditional on the compiler supporting
a each language version, like we already handle C++11.

Currently no testcases are actually run in this way for these
newer language versions.
2022-07-26 15:28:51 +12:00
William S Fulton 35ec8ca210 Add argcargv test case to test-suite 2022-05-15 19:49:59 +01:00
William S Fulton 5cc4591ae7 Consistent cpp11 testing in test-suite
Move HAVE_CXX11 into makefiles so that running test-suite
from top level directory or in the language's test-suite directory
is consistent. For example, running 'make check-java-test-suite'
behaves the same as 'cd Examples/test-suite/java && make check'.
2022-03-27 19:34:20 +01:00
William S Fulton d1b93f2c0e Merge branch 'feature/python-builtin-separate-runtime-data'
* feature/python-builtin-separate-runtime-data:
  Rework swig_and_compile_multi_cpp makefile helper
  Different capsule names for builtin changes entry
  Use different capsule names with and without -builtin

Conflicts:
	CHANGES.current
2022-03-26 15:18:55 +00:00
William S Fulton f2dd436a5b Rework swig_and_compile_multi_cpp makefile helper
Seems less cryptic and more maintainable to me
2022-03-26 15:16:22 +00:00
Eugene Toder f733efd3c0 Use different capsule names with and without -builtin
Types generated with and without -builtin are not compatible. Mixing
them in a common type list leads to crashes. Avoid this by using
different capsule names: "type_pointer_capsule" without -builtin and
"type_pointer_capsule_builtin" with.

See #1684
2022-03-18 13:44:54 -04:00
Julien Schueller 484e5316f2 Python: Option to generate flat class methods 2022-03-18 11:10:14 +01:00
Olly Betts c7af8eabb3 Default to running tests with Python 3
Specify PY2=1 to use Python 2.

See #1779
Closes #2235
2022-03-17 18:55:10 +13:00
William S Fulton 3159de3e9f Add support for Python variable annotations as a feature.
Both function annotations and variable annotations are turned on using the
"python:annotations" feature. Example:

  %feature("python:annotations", "c");

  struct V {
    float val;
  };

The generated code contains a variable annotation containing the C float type:

  class V(object):
      val: "float" = property(_example.V_val_get, _example.V_val_set)
      ...

Python 3.5 and earlier do not support variable annotations, so variable
annotations can be turned off with a "python:annotations:novar" feature flag.
Example turning on function annotations but not variable annotations globally:

  %feature("python:annotations", "c");
  %feature("python:annotations:novar");

or via the command line:

  -features python:annotations=c,python:annotations:novar

Closes #1951
2022-03-02 19:33:03 +00:00
William S Fulton 2072ae19c9 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
2022-02-27 10:47:50 +00:00
Seth R Johnson fc2b90acd1 Add a "diamond" pattern to multi-impmort test
This tests whether multiple modules can correctly import
the same common module.

```
a -> d
  -> b -> c -> d*
```
2022-02-12 19:40:03 -05:00
William S Fulton 2272d00c1a Add Python testcase for testing flatstaticmethod syntax
For testing legacy flattened static method access for when
issue #2137 is applied.
2022-01-15 00:05:06 +00:00
William S Fulton f318bb8286 Add missing clean targets
template_typedef_cplx2 files are generated by the template_typedef_import.multicpptest
but can also be cleaned by the template_typedef_cplx2.cpptest target.
2020-10-10 15:02:26 +01:00
William S Fulton fd592fdc3b Split C complex.h from C++ complex testing 2020-10-10 15:01:29 +01:00