mirror of https://github.com/swig/swig.git
Follow-up work on top of the initial Python 2.x removal: it finishes the removal and fixes several issues found while reviewing the change. Correctness fixes: - pyrun.swg: SwigPyPacked_str passed the type name straight to PyUnicode_FromFormat as its format string, so a type name containing a '%' would be misinterpreted. Use PyUnicode_FromString instead. - Doc/Manual/Varargs.html: the (...) varargs freearg typemap example lost its free() loop when the surrounding Python 2 guard was removed, leaking the memory the in typemap allocates. Restore the loop, now unconditional. - Doc/Manual/Typemaps.html: the PyInt_Check to PyLong_Check substitution left two typecheck excerpts reading PyLong_Check || PyLong_Check; collapse each back to a single check. Code generator (Source/Modules/python.cxx): - Emit the native class X(..., metaclass=_SwigNonDynamicMeta) form for nondynamic classes in all three base-list branches (object, Exception and explicit bases), and drop the Python 2 _swig_add_metaclass helper. - Emit a plain import builtins as __builtin__ instead of the Python 2 try/except import fallback. - Update a stale Python 2.x comment. Remove the deprecated embed.i library (it only ever worked with Python 2): - Delete Lib/python/embed.i and the Lib/python/Makefile.in reference to it. - Remove the python_static and python_static_cpp targets from Examples/Makefile.in and the now-orphaned static: targets that used them from the Examples/python example Makefiles. - Remove the embed.i section from the manual. Python test suite (Examples/test-suite/python): - profiletest_runme.py: convert the Python 2 print statements to print(). - doxygen_constructors_runme.py: drop the dead sys.version_info < (3, 0) branch, keeping the Python 3 super().__init__() form. - li_cdata_bytes_runme.py and li_cdata_bytes_cpp_runme.py: drop the dead exit-on-Python-2 version guard. - file_test_runme.py and python_abstractbase_runme.py: drop the now-unused import sys left behind by guard removal. Documentation (Doc/Manual/Python.html): - Drop the embed.i and SWIG_PYTHON_STRICT_UNICODE_WCHAR sections; the latter macro was Python 2 only and no longer exists, wide strings are unicode-only by default. - De-duplicate the %pythonabc example and drop a stale collections.abc compatibility note. - Update the version support statement and other stale Python 2 mentions. Other cleanups: - Tools/mkdist.py: raise the minimum Python version check to Python 3. - Reword stale Python 2 comments in pyrun.swg, pyiterators.swg and pycontainer.swg, and fix a PyString_FromFormat left in a pyclasses.swg doc comment. - CHANGES.current: record that Python 2 support has been dropped. Assisted-by: Claude Code (Opus 4.8) |
||
|---|---|---|
| .. | ||
| py3 | ||
| Makefile | ||
| README | ||
| runme.py | ||
README
This example tests the %import directive and python import from __init__.py.
This case is not correctly handled by swig 2.
The issue was reported as Source Forge bug #1297 and later as GitHub issue #7.
Use 'python runme.py' to run a test.
Overview:
---------
The example defines 2 different extension modules--each wrapping a separate C++
class.
pyX/pkg2/pkg3/pkg4/foo.i - Pkg4_Foo class
pyX/pkg2/bar.i - Pkg2_Bar class derived from Pkg4_Foo
and the package pyX.pkg2 has:
pyX/pkg2/__init__.py - which imports something from "bar" module
For example with python 2.x the py2/pkg2/__init__.py imports Pkg2_Bar class as
follows
from bar import Pkg2_Bar # [1]
Such cases doesn't work when fully qualified python module names are used by
swig to generate python import directives (SF bug 1297). The generated file
"py2/pkg2/bar.py" has following lines:
import py2.pkg2.pkg3.pkg4.foo # [2]
class Pkg2_Bar(py2.pkg2.pkg3.pkg4.foo.P1_S1_S2_Foo): # [3]
and it's not possible to import anything from py2.pkg2 subpackage, e.g.
import py2.pkg2
fails with the following exception:
Traceback (most recent call last):
File "runme.py", line 3, in <module>
import py2.pkg2
File "py2/pkg2/__init__.py", line 4, in <module>
from bar import Pkg2_Bar
File "py2/pkg2/bar.py", line 71, in <module>
class Pkg2_Bar(py2.pkg2.pkg3.pkg4.foo.Pkg4_Foo):
AttributeError: 'module' object has no attribute 'pkg2'
It seems like during the import [1], the subpackage pkg2 is not yet fully
initialized, so py2.pkg2 can't be used. The above exception is raised at
line [3]. The problem disappears, for example, if we force swig to use relative
package names.
The difference between this ('from_init3') case and the case
'from_init2' is that here we import base class from module
pyX.pkg2.pkg3.pkg4.foo, which is nested deeper than it was in
'from_init2'. This is just to ensure, that two (and more) levels of
subpackages get imported correctly by generated python code, i.e, not only
'pkg3.foo' is handled properly (one-level subpackage) but the code works also
for 'pkg3.pkg4.foo', and so on.
If everything works well, the package pyX.pkg2 shall load properly.
Unix:
-----
- Run make
- Run the test as described above