summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaoyu Bai <divinekid@gmail.com>2008-09-11 17:18:07 +0000
committerHaoyu Bai <divinekid@gmail.com>2008-09-11 17:18:07 +0000
commit3d8ddfc442f1f73bc2c567aaa972680d14fea0df (patch)
treeffeaec4356d84b5e1764b38fa97582fc388906da
parent761ef2b98fac9926fadafcac483fe71af092d0a9 (diff)
downloadswig-3d8ddfc442f1f73bc2c567aaa972680d14fea0df.tar.gz
Merged the Python 3.0 support branch. The merging progress is not so smooth, so hope this commit won't make anything broken.
This is the (incomplemete) log produced by svnmerge.py: Merged revisions 10405-10409,10420-10422,10426,10438,10445,10451,10454-10465,10467,10473-10475,10485,10488-10489,10493-10495,10497,10509-10510,10513-10514,10517,10520,10525,10528-10529,10533-10535,10554-10557,10570,10573,10593,10614,10666-10669,10673,10678,10687,10690,10704-10706,10731,10744,10750-10752,10755,10759,10770,10775-10776,10813,10819 via svnmerge from https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-bhy git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10834 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r--Doc/Manual/Python.html253
-rw-r--r--Examples/GIFPlot/Python/full/Makefile3
-rw-r--r--Examples/GIFPlot/Python/shadow/Makefile3
-rw-r--r--Examples/GIFPlot/Python/simple/Makefile3
-rw-r--r--Examples/Makefile.in60
-rw-r--r--Examples/python/callback/Makefile1
-rw-r--r--Examples/python/class/Makefile1
-rw-r--r--Examples/python/constants/Makefile1
-rw-r--r--Examples/python/contract/Makefile1
-rw-r--r--Examples/python/docstrings/Makefile1
-rw-r--r--Examples/python/enum/Makefile1
-rw-r--r--Examples/python/exception/Makefile1
-rw-r--r--Examples/python/exceptproxy/Makefile1
-rw-r--r--Examples/python/extend/Makefile1
-rw-r--r--Examples/python/funcptr/Makefile1
-rw-r--r--Examples/python/funcptr2/Makefile1
-rw-r--r--Examples/python/functor/Makefile1
-rw-r--r--Examples/python/import/Makefile1
-rw-r--r--Examples/python/import_template/Makefile1
-rw-r--r--Examples/python/libffi/Makefile1
-rw-r--r--Examples/python/multimap/Makefile1
-rw-r--r--Examples/python/multimap/example.i32
-rw-r--r--Examples/python/operator/Makefile1
-rw-r--r--Examples/python/pointer/Makefile1
-rw-r--r--Examples/python/reference/Makefile1
-rw-r--r--Examples/python/simple/Makefile1
-rw-r--r--Examples/python/smartptr/Makefile1
-rw-r--r--Examples/python/std_map/Makefile1
-rw-r--r--Examples/python/std_vector/Makefile1
-rw-r--r--Examples/python/swigrun/Makefile1
-rw-r--r--Examples/python/template/Makefile1
-rw-r--r--Examples/python/varargs/Makefile1
-rw-r--r--Examples/python/variables/Makefile1
-rw-r--r--Examples/python/weave/Makefile1
-rw-r--r--Examples/test-suite/common.mk1
-rw-r--r--Examples/test-suite/li_cstring.i8
-rw-r--r--Examples/test-suite/li_cwstring.i8
-rw-r--r--Examples/test-suite/name_warnings.i3
-rw-r--r--Examples/test-suite/namespace_typemap.i2
-rw-r--r--Examples/test-suite/operbool.i10
-rw-r--r--Examples/test-suite/python/Makefile.in67
-rw-r--r--Examples/test-suite/python/README6
-rw-r--r--Examples/test-suite/python/abstractbase.i18
-rw-r--r--Examples/test-suite/python/abstractbase_runme3.py8
-rw-r--r--Examples/test-suite/python/cpp_namespace_runme.py20
-rw-r--r--Examples/test-suite/python/director_classic_runme.py68
-rw-r--r--Examples/test-suite/python/director_exception_runme.py1
-rw-r--r--Examples/test-suite/python/file_test_runme.py3
-rw-r--r--Examples/test-suite/python/hugemod.pl8
-rw-r--r--Examples/test-suite/python/operbool_runme.py4
-rw-r--r--Examples/test-suite/python/pybuf.i34
-rw-r--r--Examples/test-suite/python/pybuf_benchmark.i31
-rw-r--r--Examples/test-suite/python/pybuf_benchmark_runme.py16
-rw-r--r--Examples/test-suite/python/pybuf_benchmark_runme3.py16
-rw-r--r--Examples/test-suite/python/pybuf_runme3.py15
-rw-r--r--Examples/test-suite/python/template_typedef_cplx2_runme.py13
-rw-r--r--Examples/test-suite/python/template_typedef_cplx_runme.py13
-rw-r--r--Lib/python/file.i4
-rw-r--r--Lib/python/pyabc.i10
-rw-r--r--Lib/python/pyapi.swg14
-rw-r--r--Lib/python/pybuffer.i107
-rw-r--r--Lib/python/pycontainer.swg61
-rw-r--r--Lib/python/pyerrors.swg6
-rw-r--r--Lib/python/pyhead.swg44
-rw-r--r--Lib/python/pyinit.swg68
-rw-r--r--Lib/python/pyiterators.swg8
-rw-r--r--Lib/python/pyopers.swg6
-rw-r--r--Lib/python/pyrun.swg113
-rw-r--r--Lib/python/pystrings.swg20
-rw-r--r--Lib/python/pywstrings.swg2
-rw-r--r--Lib/python/std_map.i4
-rw-r--r--Source/CParse/cscanner.c18
-rw-r--r--Source/CParse/parser.y8
-rw-r--r--Source/Modules/python.cxx498
-rw-r--r--configure.in107
75 files changed, 1605 insertions, 248 deletions
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html
index 62b72fabf..c0b71b52d 100644
--- a/Doc/Manual/Python.html
+++ b/Doc/Manual/Python.html
@@ -46,7 +46,7 @@
<li><a href="#Python_nn30">Memory management</a>
<li><a href="#Python_nn31">Python 2.2 and classic classes</a>
</ul>
-<li><a href="#directors">Cross language polymorphism</a>
+<li><a href="#Python_directors">Cross language polymorphism</a>
<ul>
<li><a href="#Python_nn33">Enabling directors</a>
<li><a href="#Python_nn34">Director classes</a>
@@ -101,6 +101,12 @@
<li><a href="#Python_nn71">%feature("docstring")</a>
</ul>
<li><a href="#Python_nn72">Python Packages</a>
+<li><a href="#Python_python3support">Python 3 Support</a>
+<ul>
+<li><a href="#Python_nn74">Function annotation</a>
+<li><a href="#Python_nn75">Buffer interface</a>
+<li><a href="#Python_nn76">Abstract base classes</a>
+</ul>
</ul>
</div>
<!-- INDEX -->
@@ -113,9 +119,9 @@
<p>
This chapter describes SWIG's support of Python. SWIG is compatible
-with most recent Python versions including Python 2.2 as well as older
-versions dating back to Python 1.5.2. For the best results, consider using Python
-2.0 or newer.
+with most recent Python versions including Python 3.0 and Python 2.6,
+as well as older versions dating back to Python 2.0. For the best results,
+consider using Python 2.3 or newer.
</p>
<p>
@@ -2544,7 +2550,7 @@ class itself. In Python-2.1 and earlier, they have to be accessed as a global
function or through an instance (see the earlier section).
</p>
-<H2><a name="directors"></a>30.5 Cross language polymorphism</H2>
+<H2><a name="Python_directors"></a>30.5 Cross language polymorphism</H2>
<p>
@@ -4929,7 +4935,7 @@ with more than one line.
<p>
Using the <tt>package</tt> option of the <tt>%module</tt> directive
allows you to specify what Python package that the module will be
-living in when installed.
+living in when installed.
</p>
<div class="code">
@@ -4950,6 +4956,241 @@ and also in base class declarations, etc. if the package name is
different than its own.
</p>
+<H2><a name="Python_python3support"></a>30.12 Python 3 Support</H2>
+
+
+<p>
+SWIG is able to support Python 3.0. The wrapper code generated by
+SWIG can be compiled with both Python 2.x or 3.0. Further more, by
+passing the <tt>-py3</tt> command line option to SWIG, wrapper code
+with some Python 3 specific features can be generated (see below
+subsections for details of these features). The <tt>-py3</tt> option also
+disables some incompatible features for Python 3, such as
+<tt>-classic</tt>.
+
+<p>
+There is a list of known-to-be-broken features in Python 3:
+</p>
+<ul>
+ <li>No more support for FILE* typemaps, because PyFile_AsFile has been dropped
+ in Python 3.</li>
+ <li>The <tt>-apply</tt> command line option is removed and generating
+ code using apply() is no longer supported.</li>
+</ul>
+
+<p>
+The following are Python 3.0 new features that are currently supported by
+SWIG.
+</p>
+
+<H3><a name="Python_nn74"></a>30.12.1 Function annotation</H3>
+
+
+<p>
+The <tt>-py3</tt> option will enable function annotation support. When used
+SWIG is able to generate proxy method definitions like
+this:
+</p>
+
+<div class="code"><pre>
+ def foo(self, bar : "int" = 0) -&gt; "void" : ...
+</pre></div>
+
+<p>
+For details of usage of function annotation, see PEP 3107.
+</p>
+
+<H3><a name="Python_nn75"></a>30.12.2 Buffer interface</H3>
+
+
+<p>
+Buffer protocols were revised in Python 3. SWIG also gains a series of
+new typemaps to support buffer interfaces. These typemap macros are
+defined in <tt>pybuffer.i</tt>, which must be included in order to use them.
+By using these typemaps, your wrapped function will be able to
+accept any Python object that exposes a suitable buffer interface.
+</p>
+
+<p>
+For example, the <tt>get_path()</tt> function puts the path string
+into the memory pointed to by its argument:
+</p>
+
+<div class="code"><pre>
+void get_path(char *s);
+</pre></div>
+
+<p>
+Then you can write a typemap like this: (the following example is
+applied to both Python 3.0 and 2.6, since the <tt>bytearray</tt> type
+is backported to 2.6.
+</p>
+
+
+<div class="code"><pre>
+%include &lt;pybuffer.i&gt;
+%pybuffer_mutable_string(char *str);
+void get_path(char *s);
+</pre></div>
+
+<p>
+And then on the Python side the wrapped <tt>get_path</tt> could be used in this
+way:
+</p>
+
+<div class="targetlang"><pre>
+&gt;&gt;&gt; p = bytearray(10)
+&gt;&gt;&gt; get_path(p)
+&gt;&gt;&gt; print(p)
+bytearray(b'/Foo/Bar/\x00')
+</pre></div>
+
+<p>
+The macros defined in <tt>pybuffer.i</tt> are similar to those in
+<tt>cstring.i</tt>:
+</p>
+
+<p>
+<b>%pybuffer_mutable_binary(parm, size_parm)</b>
+</p>
+
+<div class="indent">
+
+<p>
+The macro can be used to generate a typemap which maps a buffer of an
+object to a pointer provided by <tt>parm</tt> and a size argument
+provided by <tt>size_parm</tt>. For example:
+</p>
+
+<div class="code"><pre>
+%pybuffer_mutable_binary(char *str, size_t size);
+...
+int snprintf(char *str, size_t size, const char *format, ...);
+</pre></div>
+
+<p>
+In Python:
+</p>
+
+<div class="targetlang"><pre>
+&gt;&gt;&gt; buf = bytearray(6)
+&gt;&gt;&gt; snprintf(buf, "Hello world!")
+&gt;&gt;&gt; print(buf)
+bytearray(b'Hello\x00')
+&gt;&gt;&gt;
+</pre></div>
+
+</div>
+
+<p>
+<b>%pybuffer_mutable_string(parm)</b>
+</p>
+
+<div class="indent">
+
+<p>
+This typemap macro requires the buffer to be a zero terminated string,
+and maps the pointer of the buffer to <tt>parm</tt>. For example:
+</p>
+
+<div class="code"><pre>
+%pybuffer_mutable_string(char *str);
+...
+size_t make_upper(char *str);
+</pre></div>
+
+<p>
+In Python:
+</p>
+
+<div class="targetlang"><pre>
+&gt;&gt;&gt; buf = bytearray(b'foo\x00')
+&gt;&gt;&gt; make_upper(buf)
+&gt;&gt;&gt; print(buf)
+bytearray(b'FOO\x00')
+&gt;&gt;&gt;
+</pre></div>
+
+<p>
+Both <tt>%pybuffer_mutable_binary</tt> and <tt>%pybuffer_mutable_string</tt>
+require the provided buffer to be mutable, eg. they can accept a
+<tt>bytearray</tt> type but can't accept an immutable <tt>byte</tt>
+type.
+</p>
+
+</div>
+
+<p>
+<b>%pybuffer_binary(parm, size_parm)</b>
+</p>
+
+<div class="indent">
+
+<p>
+This macro maps an object's buffer to a pointer <tt>parm</tt> and a
+size <tt>size_parm</tt>. It is similar to
+<tt>%pybuffer_mutable_binary</tt>, except the
+<tt>%pybuffer_binary</tt> an accept both mutable and immutable
+buffers. As a result, the wrapped function should not modify the buffer.
+</p>
+
+</div>
+
+<p>
+<b>%pybuffer_string(parm)</b>
+</p>
+
+<div class="indent">
+
+<p>
+This macro maps an object's buffer as a string pointer <tt>parm</tt>.
+It is similar to <tt>%pybuffer_mutable_string</tt> but the buffer
+could be both mutable and immutable. And your function should not
+modify the buffer.
+</p>
+
+</div>
+
+
+<H3><a name="Python_nn76"></a>30.12.3 Abstract base classes</H3>
+
+
+<p>
+By including <tt>pyabc.i</tt> and using the <tt>-py3</tt> command
+line option when calling SWIG, the proxy classes of the STL containers
+will automatically gain an appropriate abstract base class. For
+example, the following SWIG interface:
+</p>
+
+<div class="code"><pre>
+%include &lt;pyabc.i&gt;
+%include &lt;std_map.i&gt;
+%include &lt;std_list.i&gt;
+
+namespace std {
+ %template(Mapii) map&lt;int, int&gt;;
+ %template(IntList) list&lt;int&gt;;
+}
+</pre></div>
+
+<p>
+will generate a Python proxy class <tt>Mapii</tt> inheriting from
+<tt>collections.MutableMap</tt> and a proxy class <tt>IntList</tt>
+inheriting from <tt>collections.MutableSequence</tt>.
+</p>
+
+<p>
+<tt>pyabc.i</tt> also provides a macro <tt>%pythonabc</tt> that could be
+used to define an abstract base class for your own C++ class:
+</p>
+
+<div class="code"><pre>
+%pythonabc(MySet, collections.MutableSet);
+</pre></div>
+
+<p>
+For details of abstract base class, please see PEP 3119.
+</p>
</body>
</html>
diff --git a/Examples/GIFPlot/Python/full/Makefile b/Examples/GIFPlot/Python/full/Makefile
index ae927b72b..83a7c864b 100644
--- a/Examples/GIFPlot/Python/full/Makefile
+++ b/Examples/GIFPlot/Python/full/Makefile
@@ -1,5 +1,5 @@
TOP = ../../..
-SWIG = $(TOP)/../swig
+SWIG = $(TOP)/../preinst-swig
SWIGOPT = -I../../Include
SRCS =
TARGET = gifplot
@@ -23,3 +23,4 @@ clean::
rm -f *.gif
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/GIFPlot/Python/shadow/Makefile b/Examples/GIFPlot/Python/shadow/Makefile
index 1f5014895..73fca9673 100644
--- a/Examples/GIFPlot/Python/shadow/Makefile
+++ b/Examples/GIFPlot/Python/shadow/Makefile
@@ -1,5 +1,5 @@
TOP = ../../..
-SWIG = $(TOP)/../swig
+SWIG = $(TOP)/../preinst-swig
SWIGOPT = -I../../Interface
SRCS =
TARGET = gifplot
@@ -23,3 +23,4 @@ clean::
rm -f *.gif
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/GIFPlot/Python/simple/Makefile b/Examples/GIFPlot/Python/simple/Makefile
index 5eb0344e8..9fc9a6c72 100644
--- a/Examples/GIFPlot/Python/simple/Makefile
+++ b/Examples/GIFPlot/Python/simple/Makefile
@@ -1,5 +1,5 @@
TOP = ../../..
-SWIG = $(TOP)/../swig
+SWIG = $(TOP)/../preinst-swig
SWIGOPT =
SRCS =
TARGET = simple
@@ -23,3 +23,4 @@ clean::
rm -f *.gif
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/Makefile.in b/Examples/Makefile.in
index 555aa3e92..f85075906 100644
--- a/Examples/Makefile.in
+++ b/Examples/Makefile.in
@@ -223,19 +223,39 @@ perl5_clean:
##################################################################
# Make sure these locate your Python installation
-PYTHON_INCLUDE= $(DEFS) @PYINCLUDE@
-PYTHON_LIB = @PYLIB@
-
-# Extra Python specific dynamic linking options
-PYTHON_DLNK = @PYTHONDYNAMICLINKING@
+ifeq (,$(PY3))
+ PYTHON_INCLUDE= $(DEFS) @PYINCLUDE@
+ PYTHON_LIB = @PYLIB@
+ PYTHON = @PYTHON@
+else
+ PYTHON_INCLUDE= $(DEFS) @PY3INCLUDE@
+ PYTHON_LIB = @PY3LIB@
+ PYTHON = @PYTHON3@
+endif
+
+# Extra Python specific linking options
+ifeq (,$(PY3))
+ PYTHON_DLNK = @PYTHONDYNAMICLINKING@
+ PYTHON_LINK = @PYLINK@
+else
+ PYTHON_DLNK = @PYTHON3DYNAMICLINKING@
+ PYTHON_LINK = @PY3LINK@
+endif
PYTHON_SO = @PYTHON_SO@
+# SWIG option for Python
+ifeq (,$(PY3))
+ SWIGPYTHON = $(SWIG) -python
+else
+ SWIGPYTHON = $(SWIG) -python -py3
+endif
+
# ----------------------------------------------------------------
# Build a C dynamically loadable module
# ----------------------------------------------------------------
python: $(SRCS)
- $(SWIG) -python $(SWIGOPT) $(INTERFACE)
+ $(SWIGPYTHON) $(SWIGOPT) $(INTERFACE)
$(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDES) $(PYTHON_INCLUDE)
$(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO)
@@ -244,7 +264,7 @@ python: $(SRCS)
# -----------------------------------------------------------------
python_cpp: $(SRCS)
- $(SWIG) -c++ -python $(SWIGOPT) $(INTERFACE)
+ $(SWIGPYTHON) -c++ $(SWIGOPT) $(INTERFACE)
$(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(PYTHON_INCLUDE)
$(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO)
@@ -257,18 +277,37 @@ python_cpp: $(SRCS)
#TKINTER = -L/usr/X11R6.3/lib -L/usr/local/compat/lib -ltk4.0 -ltcl7.4 -lX11
TKINTER =
-PYTHON_LIBOPTS = @PYLINK@ @LIBS@ $(TKINTER) $(SYSLIBS)
+PYTHON_LIBOPTS = $(PYTHON_LINK) @LIBS@ $(TKINTER) $(SYSLIBS)
python_static: $(SRCS)
- $(SWIG) -python -lembed.i $(SWIGOPT) $(INTERFACE)
+ $(SWIGPYTHON) -lembed.i $(SWIGOPT) $(INTERFACE)
$(CC) $(CFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCS) $(INCLUDES) \
$(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET)
python_static_cpp: $(SRCS)
- $(SWIG) -c++ -python -lembed.i $(SWIGOPT) $(INTERFACE)
+ $(SWIGPYTHON) -c++ -lembed.i $(SWIGOPT) $(INTERFACE)
$(CXX) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) \
$(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET)
+# -----------------------------------------------------------------
+# Running a Python example
+# -----------------------------------------------------------------
+
+ifeq (,$(PY3))
+ SCRIPT = runme.py
+else
+ SCRIPT = runme3.py
+endif
+
+PY2TO3 = 2to3 `2to3 -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'`
+
+python_run: $(SCRIPT)
+ env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(PYTHON) $(SCRIPT) >/dev/null
+
+runme3.py: runme.py
+ cp $< $@
+ $(PY2TO3) -w $@ >/dev/null 2>&1
+
# -----------------------------------------------------------------
# Cleaning the python examples
# -----------------------------------------------------------------
@@ -278,6 +317,7 @@ python_clean:
rm -f core @EXTRA_CLEAN@
rm -f *.@OBJEXT@ *@SO@ *@PYTHON_SO@
+
##################################################################
##### OCTAVE ######
##################################################################
diff --git a/Examples/python/callback/Makefile b/Examples/python/callback/Makefile
index ad36d7d7e..a29276e58 100644
--- a/Examples/python/callback/Makefile
+++ b/Examples/python/callback/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/class/Makefile b/Examples/python/class/Makefile
index f331b8203..74625b992 100644
--- a/Examples/python/class/Makefile
+++ b/Examples/python/class/Makefile
@@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/constants/Makefile b/Examples/python/constants/Makefile
index 01d0f943a..1420b4e0b 100644
--- a/Examples/python/constants/Makefile
+++ b/Examples/python/constants/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/contract/Makefile b/Examples/python/contract/Makefile
index c7b476995..77fe94b1a 100644
--- a/Examples/python/contract/Makefile
+++ b/Examples/python/contract/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/docstrings/Makefile b/Examples/python/docstrings/Makefile
index 74ab112a1..f25450cac 100644
--- a/Examples/python/docstrings/Makefile
+++ b/Examples/python/docstrings/Makefile
@@ -21,3 +21,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/enum/Makefile b/Examples/python/enum/Makefile
index f331b8203..74625b992 100644
--- a/Examples/python/enum/Makefile
+++ b/Examples/python/enum/Makefile
@@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/exception/Makefile b/Examples/python/exception/Makefile
index 17c4f30b7..7dbdde944 100644
--- a/Examples/python/exception/Makefile
+++ b/Examples/python/exception/Makefile
@@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/exceptproxy/Makefile b/Examples/python/exceptproxy/Makefile
index a4f334311..ba5c79827 100644
--- a/Examples/python/exceptproxy/Makefile
+++ b/Examples/python/exceptproxy/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/extend/Makefile b/Examples/python/extend/Makefile
index ad36d7d7e..a29276e58 100644
--- a/Examples/python/extend/Makefile
+++ b/Examples/python/extend/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/funcptr/Makefile b/Examples/python/funcptr/Makefile
index 4a1e1bb71..0f4a1e077 100644
--- a/Examples/python/funcptr/Makefile
+++ b/Examples/python/funcptr/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/funcptr2/Makefile b/Examples/python/funcptr2/Makefile
index 4a1e1bb71..0f4a1e077 100644
--- a/Examples/python/funcptr2/Makefile
+++ b/Examples/python/funcptr2/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/functor/Makefile b/Examples/python/functor/Makefile
index c45536529..fe389757a 100644
--- a/Examples/python/functor/Makefile
+++ b/Examples/python/functor/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/import/Makefile b/Examples/python/import/Makefile
index e00e81864..74d4f88cf 100644
--- a/Examples/python/import/Makefile
+++ b/Examples/python/import/Makefile
@@ -19,3 +19,4 @@ clean::
@rm -f foo.py bar.py spam.py base.py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/import_template/Makefile b/Examples/python/import_template/Makefile
index fa49f3145..ee47e994d 100644
--- a/Examples/python/import_template/Makefile
+++ b/Examples/python/import_template/Makefile
@@ -19,3 +19,4 @@ clean::
@rm -f foo.py bar.py spam.py base.py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/libffi/Makefile b/Examples/python/libffi/Makefile
index 8c7edfa65..fafb7de09 100644
--- a/Examples/python/libffi/Makefile
+++ b/Examples/python/libffi/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/multimap/Makefile b/Examples/python/multimap/Makefile
index 4a1e1bb71..0f4a1e077 100644
--- a/Examples/python/multimap/Makefile
+++ b/Examples/python/multimap/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/multimap/example.i b/Examples/python/multimap/example.i
index 163d7cc8e..3d5a09771 100644
--- a/Examples/python/multimap/example.i
+++ b/Examples/python/multimap/example.i
@@ -17,6 +17,7 @@ extern int gcd(int x, int y);
%typemap(in,fragment="t_output_helper") (int argc, char *argv[]) {
int i;
+ int l;
if (!PyList_Check($input)) {
SWIG_exception(SWIG_ValueError, "Expecting a list");
}
@@ -27,11 +28,21 @@ extern int gcd(int x, int y);
$2 = (char **) malloc(($1+1)*sizeof(char *));
for (i = 0; i < $1; i++) {
PyObject *s = PyList_GetItem($input,i);
- if (!PyString_Check(s)) {
+%#if PY_VERSION_HEX >= 0x03000000
+ if (!PyUnicode_Check(s))
+%#else
+ if (!PyString_Check(s))
+%#endif
+ {
free($2);
SWIG_exception(SWIG_ValueError, "List items must be strings");
}
+%#if PY_VERSION_HEX >= 0x03000000
+ $2[i] = PyUnicode_AsStringAndSize(s, &l);
+%#else
$2[i] = PyString_AsString(s);
+%#endif
+
}
$2[i] = 0;
}
@@ -39,12 +50,21 @@ extern int gcd(int x, int y);
extern int gcdmain(int argc, char *argv[]);
%typemap(in) (char *bytes, int len) {
+
+%#if PY_VERSION_HEX >= 0x03000000
+ if (!PyUnicode_Check($input)) {
+ PyErr_SetString(PyExc_ValueError,"Expected a string");
+ return NULL;
+ }
+ $1 = PyUnicode_AsStringAndSize($input, &$2);
+%#else
if (!PyString_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a string");
return NULL;
}
$1 = PyString_AsString($input);
$2 = PyString_Size($input);
+%#endif
}
extern int count(char *bytes, int len, char c);
@@ -56,9 +76,15 @@ extern int count(char *bytes, int len, char c);
so that we don't violate it's mutability */
%typemap(in) (char *str, int len) {
+%#if PY_VERSION_HEX >= 0x03000000
+ $2 = PyUnicode_GetSize($input);
+ $1 = (char *) malloc($2+1);
+ memmove($1,PyUnicode_AsString($input),$2);
+%#else
$2 = PyString_Size($input);
$1 = (char *) malloc($2+1);
memmove($1,PyString_AsString($input),$2);
+%#endif
}
/* Return the mutated string as a new object. The t_output_helper
@@ -67,7 +93,11 @@ extern int count(char *bytes, int len, char c);
%typemap(argout) (char *str, int len) {
PyObject *o;
+%#if PY_VERSION_HEX >= 0x03000000
+ o = PyUnicode_FromStringAndSize($1,$2);
+%#else
o = PyString_FromStringAndSize($1,$2);
+%#endif
$result = t_output_helper($result,o);
free($1);
}
diff --git a/Examples/python/operator/Makefile b/Examples/python/operator/Makefile
index c45536529..fe389757a 100644
--- a/Examples/python/operator/Makefile
+++ b/Examples/python/operator/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/pointer/Makefile b/Examples/python/pointer/Makefile
index 4a1e1bb71..0f4a1e077 100644
--- a/Examples/python/pointer/Makefile
+++ b/Examples/python/pointer/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/reference/Makefile b/Examples/python/reference/Makefile
index f331b8203..74625b992 100644
--- a/Examples/python/reference/Makefile
+++ b/Examples/python/reference/Makefile
@@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/simple/Makefile b/Examples/python/simple/Makefile
index 4a1e1bb71..0f4a1e077 100644
--- a/Examples/python/simple/Makefile
+++ b/Examples/python/simple/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/smartptr/Makefile b/Examples/python/smartptr/Makefile
index 58d139643..f73802a6b 100644
--- a/Examples/python/smartptr/Makefile
+++ b/Examples/python/smartptr/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/std_map/Makefile b/Examples/python/std_map/Makefile
index 2d4c1b4a3..5d13da764 100644
--- a/Examples/python/std_map/Makefile
+++ b/Examples/python/std_map/Makefile
@@ -22,3 +22,4 @@ run:
python runme.py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/std_vector/Makefile b/Examples/python/std_vector/Makefile
index a4f334311..ba5c79827 100644
--- a/Examples/python/std_vector/Makefile
+++ b/Examples/python/std_vector/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/swigrun/Makefile b/Examples/python/swigrun/Makefile
index 53bf701c9..2142be5bb 100644
--- a/Examples/python/swigrun/Makefile
+++ b/Examples/python/swigrun/Makefile
@@ -22,3 +22,4 @@ clean::
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/template/Makefile b/Examples/python/template/Makefile
index a4f334311..ba5c79827 100644
--- a/Examples/python/template/Makefile
+++ b/Examples/python/template/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/varargs/Makefile b/Examples/python/varargs/Makefile
index 01d0f943a..1420b4e0b 100644
--- a/Examples/python/varargs/Makefile
+++ b/Examples/python/varargs/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/variables/Makefile b/Examples/python/variables/Makefile
index 4a1e1bb71..0f4a1e077 100644
--- a/Examples/python/variables/Makefile
+++ b/Examples/python/variables/Makefile
@@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/python/weave/Makefile b/Examples/python/weave/Makefile
index 822779bd1..88f95c095 100644
--- a/Examples/python/weave/Makefile
+++ b/Examples/python/weave/Makefile
@@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
+ $(MAKE) -f $(TOP)/Makefile python_run
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 0a3a0858a..57b57c271 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -237,6 +237,7 @@ CPP_TEST_CASES += \
null_pointer \
operator_overload \
operator_overload_break \
+ operbool \
ordering \
overload_copy \
overload_extend \
diff --git a/Examples/test-suite/li_cstring.i b/Examples/test-suite/li_cstring.i
index fd92ac7d3..28e8049e8 100644
--- a/Examples/test-suite/li_cstring.i
+++ b/Examples/test-suite/li_cstring.i
@@ -4,7 +4,7 @@
#ifndef SWIG_CSTRING_UNIMPL
-%cstring_input_binary(char *in, int n);
+%cstring_input_binary(char *str_in, int n);
%cstring_bounded_output(char *out1, 512);
%cstring_chunk_output(char *out2, 64);
%cstring_bounded_mutable(char *out3, 512);
@@ -22,13 +22,13 @@
%inline %{
-int count(char *in, int n, char c) {
+int count(char *str_in, int n, char c) {
int r = 0;
while (n > 0) {
- if (*in == c) {
+ if (*str_in == c) {
r++;
}
- in++;
+ str_in++;
--n;
}
return r;
diff --git a/Examples/test-suite/li_cwstring.i b/Examples/test-suite/li_cwstring.i
index dc9a1c4b9..769dcce12 100644
--- a/Examples/test-suite/li_cwstring.i
+++ b/Examples/test-suite/li_cwstring.i
@@ -4,7 +4,7 @@
#ifndef SWIG_CWSTRING_UNIMPL
-%cwstring_input_binary(wchar_t *in, int n);
+%cwstring_input_binary(wchar_t *str_in, int n);
%cwstring_bounded_output(wchar_t *out1, 512);
%cwstring_chunk_output(wchar_t *out2, 64);
%cwstring_bounded_mutable(wchar_t *out3, 512);
@@ -22,13 +22,13 @@
%inline %{
-int count(wchar_t *in, int n, wchar_t c) {
+int count(wchar_t *str_in, int n, wchar_t c) {
int r = 0;
while (n > 0) {
- if (*in == c) {
+ if (*str_in == c) {
r++;
}
- in++;
+ str_in++;
--n;
}
return r;
diff --git a/Examples/test-suite/name_warnings.i b/Examples/test-suite/name_warnings.i
index a9cb35686..527dbcfaa 100644
--- a/Examples/test-suite/name_warnings.i
+++ b/Examples/test-suite/name_warnings.i
@@ -58,13 +58,12 @@ namespace std
%template(max_i) max<int>;
-
%inline {
/* silently rename the parameter names in csharp/java */
#ifdef SWIGR
double foo(double inparam, double out) { return 1.0; }
#else
- double foo(double in, double out) { return 1.0; }
+ double foo(double abstract, double out) { return 1.0; }
#endif
double bar(double native, bool boolean) { return 1.0; }
}
diff --git a/Examples/test-suite/namespace_typemap.i b/Examples/test-suite/namespace_typemap.i
index e4e0af905..984b93a6f 100644
--- a/Examples/test-suite/namespace_typemap.i
+++ b/Examples/test-suite/namespace_typemap.i
@@ -75,7 +75,7 @@ namespace test {
class string_class;
#ifdef SWIGPYTHON
%typemap(in) string_class * {
- $1 = new string_class(PyString_AsString($input));
+ $1 = new string_class(SWIG_Python_str_AsChar($input));
}
%typemap(freearg) string_class * {
delete $1;
diff --git a/Examples/test-suite/operbool.i b/Examples/test-suite/operbool.i
new file mode 100644
index 000000000..d6d7fc706
--- /dev/null
+++ b/Examples/test-suite/operbool.i
@@ -0,0 +1,10 @@
+%module operbool
+
+%inline %{
+ class Test {
+ public:
+ operator bool() {
+ return false;
+ }
+ };
+%}
diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in
index 7f11cd495..a3a027453 100644
--- a/Examples/test-suite/python/Makefile.in
+++ b/Examples/test-suite/python/Makefile.in
@@ -2,14 +2,41 @@
# Makefile for python test-suite
#######################################################################
+ifeq (,$(PY3))
+ PYBIN = @PYTHON@
+else
+ PYBIN = @PYTHON3@
+endif
+
LANGUAGE = python
-PYTHON = @PYTHON@
-SCRIPTSUFFIX = _runme.py
+ifneq (,$(USE_VALGRIND))
+ PYTHON = valgrind --leak-check=full --suppressions=pyswig.supp $(PYBIN)
+else
+ PYTHON = $(PYBIN)
+endif
+
+#*_runme.py for Python 2.x, *_runme3.py for Python 3.x
+PY2SCRIPTSUFFIX = _runme.py
+PY3SCRIPTSUFFIX = _runme3.py
+
+ifeq (,$(PY3))
+ SCRIPTSUFFIX = $(PY2SCRIPTSUFFIX)
+else
+ SCRIPTSUFFIX = $(PY3SCRIPTSUFFIX)
+endif
+
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
+
+#Use the tricky command because we want to disable the "import" fixer,
+#but currently 2to3 has no option to let us do it
+PY2TO3 = 2to3 `2to3 -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'`
+
+
CPP_TEST_CASES += \
+ abstractbase \
argcargvtest \
autodoc \
callback \
@@ -77,12 +104,35 @@ VALGRIND_OPT += --suppressions=pythonswig.supp
+$(swig_and_compile_multi_cpp)
$(run_testcase)
+
+# Call 2to3 to generate Python 3.x test from the Python 2.x's *_runme.py file
+%$(PY3SCRIPTSUFFIX): %$(PY2SCRIPTSUFFIX)
+ cp $< $@
+ $(PY2TO3) -w $@ >/dev/null 2>&1
+
+
# Runs the testcase. A testcase is only run if
-# a file is found which has _runme.py appended after the testcase name.
+# a file is found which has _runme.py (or _runme3.py for Python 3) appended after the testcase name.
+
+run_python = env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(RUNTOOL) $(PYTHON) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)
+
+ifeq (,$(PY3))
run_testcase = \
if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \
- env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(RUNTOOL) $(PYTHON) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \
+ $(run_python);)\
+ fi;
+else
+py2_runme = $(srcdir)/$(SCRIPTPREFIX)$*$(PY2SCRIPTSUFFIX)
+py3_runme = $(srcdir)/$(SCRIPTPREFIX)$*$(PY3SCRIPTSUFFIX)
+
+run_testcase = \
+ if [ -f $(py2_runme) ]; then ( \
+ $(MAKE) -f $(srcdir)/Makefile $(py3_runme) && \
+ $(run_python);) \
+ elif [ -f $(py3_runme)]; then ( \
+ $(run_python);) \
fi;
+endif
# Clean: remove the generated .py file
%.clean:
@@ -101,14 +151,15 @@ cvsignore:
@echo clientdata_prop_b.py
@echo imports_a.py
@echo imports_b.py
- @echo mod_a.py mod_b.py
+ @echo mod_a.py mod_b.py
@echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.py hugemod_b.py hugemod_runme.py
@echo template_typedef_import.py
+hugemod_runme = hugemod$(SCRIPTPREFIX)
hugemod:
- perl hugemod.pl
+ perl hugemod.pl $(hugemod_runme)
$(MAKE) hugemod_a.cpptest
$(MAKE) hugemod_b.cpptest
- time $(PYTHON) hugemod_runme.py
- time $(PYTHON) hugemod_runme.py
+ sh -c "time $(PYTHON) $(hugemod_runme)"
+ sh -c "time $(PYTHON) $(hugemod_runme)"
diff --git a/Examples/test-suite/python/README b/Examples/test-suite/python/README
index b86ec5289..71db759b5 100644
--- a/Examples/test-suite/python/README
+++ b/Examples/test-suite/python/README
@@ -1,4 +1,8 @@
See ../README for common README file.
-Any testcases which have _runme.py appended after the testcase name will be detected and run.
+Any testcases which have _runme.py (or _runme3.py for Python 3) appended after the testcase name will be detected and run.
+If you intend to write a testcase for both Python 2.x and 3.x, do *not* directly put the _runme3.py in this directory. Just write Python 2.x's _runme.py testcase and it will be automatically converted to Python 3 code during test.
+
+You can run make with PY3=y to run test case with Python 3.x, eg.
+ $ make voidtest.cpptest PY3=y
diff --git a/Examples/test-suite/python/abstractbase.i b/Examples/test-suite/python/abstractbase.i
new file mode 100644
index 000000000..530f21921
--- /dev/null
+++ b/Examples/test-suite/python/abstractbase.i
@@ -0,0 +1,18 @@
+%module abstractbase
+%include <pyabc.i>
+%include <std_map.i>
+%include <std_multimap.i>
+%include <std_set.i>
+%include <std_multiset.i>
+%include <std_list.i>
+%include <std_vector.i>
+
+namespace std
+{
+ %template(Mapii) map<int, int>;
+ %template(Multimapii) multimap<int, int>;
+ %template(IntSet) set<int>;
+ %template(IntMultiset) multiset<int>;
+ %template(IntVector) vector<int>;
+ %template(IntList) list<int>;
+}
diff --git a/Examples/test-suite/python/abstractbase_runme3.py b/Examples/test-suite/python/abstractbase_runme3.py
new file mode 100644
index 000000000..13a87ee5e
--- /dev/null
+++ b/Examples/test-suite/python/abstractbase_runme3.py
@@ -0,0 +1,8 @@
+from abstractbase import *
+from collections import *
+assert issubclass(Mapii, MutableMapping)
+assert issubclass(Multimapii, MutableMapping)
+assert issubclass(IntSet, MutableSet)
+assert issubclass(IntMultiset, MutableSet)
+assert issubclass(IntVector, MutableSequence)
+assert issubclass(IntList, MutableSequence)
diff --git a/Examples/test-suite/python/cpp_namespace_runme.py b/Examples/test-suite/python/cpp_namespace_runme.py
index 3108b4f47..a454774f5 100644
--- a/Examples/test-suite/python/cpp_namespace_runme.py
+++ b/Examples/test-suite/python/cpp_namespace_runme.py
@@ -3,20 +3,20 @@ import cpp_namespace
n = cpp_namespace.fact(4)
if n != 24:
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
if cpp_namespace.cvar.Foo != 42:
- raise "Bad variable value!"
+ raise RuntimeError("Bad variable value!")
t = cpp_namespace.Test()
if t.method() != "Test::method":
- raise "Bad method return value!"
+ raise RuntimeError("Bad method return value!")
if cpp_namespace.do_method(t) != "Test::method":
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
if cpp_namespace.do_method2(t) != "Test::method":
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
cpp_namespace.weird("hello", 4)
@@ -28,18 +28,18 @@ t4 = cpp_namespace.Test4()
t5 = cpp_namespace.Test5()
if cpp_namespace.foo3(42) != 42:
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t2,40) != "Test2::method":
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t3,40) != "Test3::method":
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t4,40) != "Test4::method":
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t5,40) != "Test5::method":
- raise "Bad return value!"
+ raise RuntimeError("Bad return value!")
diff --git a/Examples/test-suite/python/director_classic_runme.py b/Examples/test-suite/python/director_classic_runme.py
index 878905679..7e18a9a61 100644
--- a/Examples/test-suite/python/director_classic_runme.py
+++ b/Examples/test-suite/python/director_classic_runme.py
@@ -1,56 +1,56 @@
from director_classic import *
class TargetLangPerson(Person):
- def __init__(self):
- Person.__init__(self)
- def id(self):
- identifier = "TargetLangPerson"
- return identifier
+ def __init__(self):
+ Person.__init__(self)
+ def id(self):
+ identifier = "TargetLangPerson"
+ return identifier
class TargetLangChild(Child):
- def __init__(self):
- Child.__init__(self)
- def id(self):
- identifier = "TargetLangChild"
- return identifier
+ def __init__(self):
+ Child.__init__(self)
+ def id(self):
+ identifier = "TargetLangChild"
+ return identifier
class TargetLangGrandChild(GrandChild):
- def __init__(self):
- GrandChild.__init__(self)
- def id(self):
- identifier = "TargetLangGrandChild"
- return identifier
+ def __init__(self):
+ GrandChild.__init__(self)
+ def id(self):
+ identifier = "TargetLangGrandChild"
+ return identifier
# Semis - don't override id() in target language
class TargetLangSemiPerson(Person):
- def __init__(self):
- Person.__init__(self)
+ def __init__(self):
+ Person.__init__(self)
# No id() override
class TargetLangSemiChild(Child):
- def __init__(self):
- Child.__init__(self)
+ def __init__(self):
+ Child.__init__(self)
# No id() override
class TargetLangSemiGrandChild(GrandChild):
- def __init__(self):
- GrandChild.__init__(self)
+ def __init__(self):
+ GrandChild.__init__(self)
# No id() override
# Orphans - don't override id() in C++
class TargetLangOrphanPerson(OrphanPerson):
- def __init__(self):
- OrphanPerson.__init__(self)
- def id(self):
- identifier = "TargetLangOrphanPerson"
- return identifier
+ def __init__(self):
+ OrphanPerson.__init__(self)
+ def id(self):
+ identifier = "TargetLangOrphanPerson"
+ return identifier
class TargetLangOrphanChild(OrphanChild):
- def __init__(self):
- Child.__init__(self)
- def id(self):
- identifier = "TargetLangOrphanChild"
- return identifier
+ def __init__(self):
+ Child.__init__(self)
+ def id(self):
+ identifier = "TargetLangOrphanChild"
+ return identifier
def check(person, expected):
@@ -61,7 +61,7 @@ def check(person, expected):
if (debug):
print(ret)
if (ret != expected):
- raise ("Failed. Received: " + ret + " Expected: " + expected)
+ raise RuntimeError("Failed. Received: " + str(ret) + " Expected: " + expected)
# Polymorphic call from C++
caller = Caller()
@@ -70,7 +70,7 @@ def check(person, expected):
if (debug):
print(ret)
if (ret != expected):
- raise ("Failed. Received: " + ret + " Expected: " + expected)
+ raise RuntimeError("Failed. Received: " + str(ret) + " Expected: " + expected)
# Polymorphic call of object created in target language and passed to C++ and back again
baseclass = caller.baseClass()
@@ -78,7 +78,7 @@ def check(person, expected):
if (debug):
print(ret)
if (ret != expected):
- raise ("Failed. Received: " + ret + " Expected: " + expected)
+ raise RuntimeError("Failed. Received: " + str(ret)+ " Expected: " + expected)
caller.resetCallback()
if (debug):
diff --git a/Examples/test-suite/python/director_exception_runme.py b/Examples/test-suite/python/director_exception_runme.py
index 28521ffa5..ef7a044f1 100644
--- a/Examples/test-suite/python/director_exception_runme.py
+++ b/Examples/test-suite/python/director_exception_runme.py
@@ -1,5 +1,4 @@
from director_exception import *
-from exceptions import *
class MyException(Exception):
def __init__(self, a, b):
diff --git a/Examples/test-suite/python/file_test_runme.py b/Examples/test-suite/python/file_test_runme.py
index 64154c619..de4e2669e 100644
--- a/Examples/test-suite/python/file_test_runme.py
+++ b/Examples/test-suite/python/file_test_runme.py
@@ -1,7 +1,8 @@
import sys
import file_test
-file_test.nfile(sys.stdout)
+if sys.version_info < (3,0):
+ file_test.nfile(sys.stdout)
cstdout = file_test.GetStdOut()
diff --git a/Examples/test-suite/python/hugemod.pl b/Examples/test-suite/python/hugemod.pl
index 15c4ce41b..5420926e4 100644
--- a/Examples/test-suite/python/hugemod.pl
+++ b/Examples/test-suite/python/hugemod.pl
@@ -2,8 +2,12 @@
use strict;
+my $modsize = 399; #adjust it so you can have a smaller or bigger hugemod
+
+my $runme = shift @ARGV;
+
open HEADER, ">hugemod.h" or die "error";
-open TEST, ">hugemod_runme.py" or die "error";
+open TEST, ">$runme" or die "error";
open I1, ">hugemod_a.i" or die "error";
open I2, ">hugemod_b.i" or die "error";
@@ -21,7 +25,7 @@ print I2 "\%inline \%{\n";
my $i;
-for ($i = 0; $i < 6000; $i++) {
+for ($i = 0; $i < $modsize; $i++) {
my $t = $i * 4;
print HEADER "class type$i { public: int a; };\n";
print I2 "class dtype$i : public type$i { public: int b; };\n";
diff --git a/Examples/test-suite/python/operbool_runme.py b/Examples/test-suite/python/operbool_runme.py
new file mode 100644
index 000000000..4218b5dd4
--- /dev/null
+++ b/Examples/test-suite/python/operbool_runme.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+import operbool
+assert not operbool.Test()
+
diff --git a/Examples/test-suite/python/pybuf.i b/Examples/test-suite/python/pybuf.i
new file mode 100644
index 000000000..207b5b7e9
--- /dev/null
+++ b/Examples/test-suite/python/pybuf.i
@@ -0,0 +1,34 @@
+%module pybuf
+%include<pybuffer.i>
+
+%pybuffer_mutable_binary(char *buf1, int len);
+%pybuffer_mutable_string(char *buf2);
+%pybuffer_binary(const char *buf3, int len);
+%pybuffer_string(const char *buf4);
+
+%inline %{
+ void func1(char *buf1, int len)
+ {
+ int i;
+ for (i=0; i<len; ++i)
+ buf1[i] = 'a';
+ return;
+ }
+ void func2(char *buf2)
+ {
+ strcpy(buf2, "Hello world!");
+ }
+ int func3(const char *buf3, int len)
+ {
+ int count = 0;
+ int i;
+ for(i=0; i<len; ++i)
+ if (isalnum(buf3[i]))
+ ++count;
+ return count;
+ }
+ int func4(const char *buf4)
+ {
+ return strlen(buf4);
+ }
+%}
diff --git a/Examples/test-suite/python/pybuf_benchmark.i b/Examples/test-suite/python/pybuf_benchmark.i
new file mode 100644
index 000000000..8a793f906
--- /dev/null
+++ b/Examples/test-suite/python/pybuf_benchmark.i
@@ -0,0 +1,31 @@
+%module pybuf_benchmark
+
+%include<pybuffer.i>
+%include<cstring.i>
+%pybuffer_mutable_string(char *str1);
+%cstring_mutable(char *str2);
+
+%inline %{
+void title(char *str) {
+ int outword = 0;
+ while(*str) {
+ if (isalnum(*str)) {
+ if (outword) {
+ outword = 1;
+ *str = toupper(*str);
+ }
+ }
+ else {
+ outword = 0;
+ }
+ str++;
+ }
+}
+
+void title1(char *str1) {
+ title(str1);
+}
+void title2(char *str2) {
+ title(str2);
+}
+%}
diff --git a/Examples/test-suite/python/pybuf_benchmark_runme.py b/Examples/test-suite/python/pybuf_benchmark_runme.py
new file mode 100644
index 000000000..6676a910b
--- /dev/null
+++ b/Examples/test-suite/python/pybuf_benchmark_runme.py
@@ -0,0 +1,16 @@
+import pybuf
+import time
+k=1000000
+n=7
+
+t=time.time()
+a = bytearray(b'hello world')
+for i in range(k):
+ pybuf.title1(a)
+print "Time used by bytearray:",time.time()-t
+
+t=time.time()
+b = 'hello world'
+for i in range(k):
+ pybuf.title2(b)
+print "Time used by string:",time.time()-t
diff --git a/Examples/test-suite/python/pybuf_benchmark_runme3.py b/Examples/test-suite/python/pybuf_benchmark_runme3.py
new file mode 100644
index 000000000..e412d5993
--- /dev/null
+++ b/Examples/test-suite/python/pybuf_benchmark_runme3.py
@@ -0,0 +1,16 @@
+import pybuf
+import time
+k=1000000
+n=7
+
+t=time.time()
+a = bytearray(b'hello world')
+for i in range(k):
+ pybuf.title1(a)
+print("Time used by bytearray:",time.time()-t)
+
+t=time.time()
+b = 'hello world'
+for i in range(k):
+ pybuf.title2(b)
+print("Time used by string:",time.time()-t)
diff --git a/Examples/test-suite/python/pybuf_runme3.py b/Examples/test-suite/python/pybuf_runme3.py
new file mode 100644
index 000000000..462736bf0
--- /dev/null
+++ b/Examples/test-suite/python/pybuf_runme3.py
@@ -0,0 +1,15 @@
+import pybuf
+buf1 = bytearray(10)
+buf2 = bytearray(50)
+
+pybuf.func1(buf1)
+assert buf1 == b'a'*10
+
+pybuf.func2(buf2)
+assert buf2.startswith(b"Hello world!\x00")
+
+count = pybuf.func3(buf2)
+assert count==10 #number of alpha and number in 'Hello world!'
+
+length = pybuf.func4(buf2)
+assert length==12
diff --git a/Examples/test-suite/python/template_typedef_cplx2_runme.py b/Examples/test-suite/python/template_typedef_cplx2_runme.py
index 030fe02d8..04c599329 100644
--- a/Examples/test-suite/python/template_typedef_cplx2_runme.py
+++ b/Examples/test-suite/python/template_typedef_cplx2_runme.py
@@ -1,4 +1,3 @@
-import string
from template_typedef_cplx2 import *
#
@@ -13,7 +12,7 @@ except:
raise RuntimeError
s = '%s' % d
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print d, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -25,7 +24,7 @@ except:
raise RuntimeError
s = '%s' % e
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print e, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -42,7 +41,7 @@ except:
raise RuntimeError
s = '%s' % c
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print c, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -54,7 +53,7 @@ except:
raise RuntimeError
s = '%s' % f
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print f, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -70,7 +69,7 @@ except:
raise RuntimeError
s = '%s' % g
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print g, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -83,7 +82,7 @@ except:
raise RuntimeError
s = '%s' % h
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print h, "is not an ArithUnaryFunction"
raise RuntimeError
diff --git a/Examples/test-suite/python/template_typedef_cplx_runme.py b/Examples/test-suite/python/template_typedef_cplx_runme.py
index 99ffcb9aa..2cd9c8348 100644
--- a/Examples/test-suite/python/template_typedef_cplx_runme.py
+++ b/Examples/test-suite/python/template_typedef_cplx_runme.py
@@ -1,4 +1,3 @@
-import string
from template_typedef_cplx import *
#
@@ -13,7 +12,7 @@ except:
raise RuntimeError
s = '%s' % d
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print d, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -25,7 +24,7 @@ except:
raise RuntimeError
s = '%s' % e
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print e, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -42,7 +41,7 @@ except:
raise RuntimeError
s = '%s' % c
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print c, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -54,7 +53,7 @@ except:
raise RuntimeError
s = '%s' % f
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print f, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -70,7 +69,7 @@ except:
raise RuntimeError
s = '%s' % g
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print g, "is not an ArithUnaryFunction"
raise RuntimeError
@@ -83,6 +82,6 @@ except:
raise RuntimeError
s = '%s' % h
-if string.find(s, 'ArithUnaryFunction') == -1:
+if str.find(s, 'ArithUnaryFunction') == -1:
print h, "is not an ArithUnaryFunction"
raise RuntimeError
diff --git a/Lib/python/file.i b/Lib/python/file.i
index c0e7d5ea9..294ab9178 100644
--- a/Lib/python/file.i
+++ b/Lib/python/file.i
@@ -20,11 +20,13 @@ SWIG_AsValFilePtr(PyObject *obj, FILE **val) {
if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
if (val) *val = (FILE *)vptr;
return SWIG_OK;
- }
+ }
+%#if PY_VERSION_HEX < 0x03000000
if (PyFile_Check(obj)) {
if (val) *val = PyFile_AsFile(obj);
return SWIG_OK;
}
+%#endif
return SWIG_TypeError;
}
}
diff --git a/Lib/python/pyabc.i b/Lib/python/pyabc.i
new file mode 100644
index 000000000..3da06b5a9
--- /dev/null
+++ b/Lib/python/pyabc.i
@@ -0,0 +1,10 @@
+%define %pythonabc(Type, Abc)
+ %feature("python:abc", #Abc) Type;
+%enddef
+%pythoncode {import collections};
+%pythonabc(std::vector, collections.MutableSequence);
+%pythonabc(std::list, collections.MutableSequence);
+%pythonabc(std::map, collections.MutableMapping);
+%pythonabc(std::multimap, collections.MutableMapping);
+%pythonabc(std::set, collections.MutableSet);
+%pythonabc(std::multiset, collections.MutableSet);
diff --git a/Lib/python/pyapi.swg b/Lib/python/pyapi.swg
index 1d5148dbf..d980f9263 100644
--- a/Lib/python/pyapi.swg
+++ b/Lib/python/pyapi.swg
@@ -27,6 +27,20 @@ typedef struct swig_const_info {
swig_type_info **ptype;
} swig_const_info;
+
+/* -----------------------------------------------------------------------------
+ * Wrapper of PyInstanceMethod_New() used in Python 3
+ * It is exported to the generated module, used for -fastproxy
+ * ----------------------------------------------------------------------------- */
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
+{
+#if PY_VERSION_HEX >= 0x03000000
+ return PyInstanceMethod_New(func);
+#else
+ return NULL;
+#endif
+}
+
#ifdef __cplusplus
#if 0
{ /* cc-mode */
diff --git a/Lib/python/pybuffer.i b/Lib/python/pybuffer.i
new file mode 100644
index 000000000..3dc4c2121
--- /dev/null
+++ b/Lib/python/pybuffer.i
@@ -0,0 +1,107 @@
+/* Impelementing buffer protocol typemaps */
+
+/* %pybuffer_mutable_binary(TYPEMAP, SIZE)
+ *
+ * Macro for functions accept mutable buffer pointer with a size.
+ * This can be used for both input and output. For example:
+ *
+ * %pybuffer_mutable_binary(char *buff, int size);
+ * void foo(char *buff, int size) {
+ * for(int i=0; i<size; ++i)
+ * buff[i]++;
+ * }
+ */
+
+%define %pybuffer_mutable_binary(TYPEMAP, SIZE)
+%typemap(in) (TYPEMAP, SIZE)
+ (int res, Py_ssize_t size = 0, void *buf = 0) {
+ res = PyObject_AsWriteBuffer($input, &buf, &size);
+ if (res<0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ $1 = ($1_ltype) buf;
+ $2 = ($2_ltype) size;
+}
+%enddef
+
+/* %pybuffer_mutable_string(TYPEMAP, SIZE)
+ *
+ * Macro for functions accept mutable zero terminated string pointer.
+ * This can be used for both input and output. For example:
+ *
+ * %pybuffer_mutable_string(char *str);
+ * void foo(char *str) {
+ * while(*str) {
+ * *str = toupper(*str);
+ * str++;
+ * }
+ */
+
+%define %pybuffer_mutable_string(TYPEMAP)
+%typemap(in) (TYPEMAP)
+ (int res, Py_ssize_t size = 0, void *buf = 0) {
+ res = PyObject_AsWriteBuffer($input, &buf, &size);
+ if (res<0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ $1 = ($1_ltype) buf;
+}
+%enddef
+
+/* pybuffer_binary(TYPEMAP, SIZE)
+ *
+ * Macro for functions accept read only buffer pointer with a size.
+ * This must be used for input. For example:
+ *
+ * %pybuffer_binary(char *buff, int size);
+ * int foo(char *buff, int size) {
+ * int count = 0;
+ * for(int i=0; i<size; ++i)
+ * if (0==buff[i]) count++;
+ * return count;
+ * }
+ */
+
+%define %pybuffer_binary(TYPEMAP, SIZE)
+%typemap(in) (TYPEMAP, SIZE)
+ (int res, Py_ssize_t size = 0, const void *buf = 0) {
+ res = PyObject_AsReadBuffer($input, &buf, &size);
+ if (res<0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ $1 = ($1_ltype) buf;
+ $2 = ($2_ltype) size;
+}
+%enddef
+
+/* %pybuffer_string(TYPEMAP, SIZE)
+ *
+ * Macro for functions accept read only zero terminated string pointer.
+ * This can be used for input. For example:
+ *
+ * %pybuffer_string(char *str);
+ * int foo(char *str) {
+ * int count = 0;
+ * while(*str) {
+ * if (isalnum(*str))
+ * count++;
+ * str++;
+ * }
+ */
+
+%define %pybuffer_string(TYPEMAP)
+%typemap(in) (TYPEMAP)
+ (int res, Py_ssize_t size = 0, const void *buf = 0) {
+ res = PyObject_AsReadBuffer($input, &buf, &size);
+ if (res<0) {
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ $1 = ($1_ltype) buf;
+}
+%enddef
+
+
+
diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg
index ed0eb7f0b..58442ef76 100644
--- a/Lib/python/pycontainer.swg
+++ b/Lib/python/pycontainer.swg
@@ -116,6 +116,17 @@ namespace std {
bool res;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
res = PyObject_Compare(v, w) < 0;
+ /* This may fall into a case of inconsistent
+ eg. ObjA > ObjX > ObjB
+ but ObjA < ObjB
+ */
+ if( PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError) )
+ {
+ /* Objects can't be compared, this mostly occured in Python 3.0 */
+ /* Compare their ptr directly for a workaround */
+ res = (v < w);
+ PyErr_Clear();
+ }
SWIG_PYTHON_THREAD_END_BLOCK;
return res;
}
@@ -597,6 +608,11 @@ namespace swig
return !(self->empty());
}
+ /* Alias for Python 3 compatibility */
+ bool __bool__() const {
+ return !(self->empty());
+ }
+
size_type __len__() const {
return self->size();
}
@@ -618,6 +634,14 @@ namespace swig
return x;
}
+ /* typemap for slice object support */
+ %typemap(in) PySliceObject* {
+ $1 = (PySliceObject *) $input;
+ }
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) PySliceObject* {
+ $1 = PySlice_Check($input);
+ }
+
Sequence* __getslice__(difference_type i, difference_type j) throw (std::out_of_range) {
return swig::getslice(self, i, j);
}
@@ -634,6 +658,43 @@ namespace swig
void __delitem__(difference_type i) throw (std::out_of_range) {
self->erase(swig::getpos(self,i));
}
+
+
+ /* Overloaded methods for Python 3 compatibility
+ * (Also useful in Python 2.x)
+ */
+ Sequence* __getitem__(PySliceObject *slice) throw (std::out_of_range) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return NULL;
+ }
+ PySlice_GetIndices(slice, self->size(), &i, &j, &step);
+ return swig::getslice(self, i, j);
+ }
+
+ void __setitem__(PySliceObject *slice, const Sequence& v)
+ throw (std::out_of_range, std::invalid_argument) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return;
+ }
+ PySlice_GetIndices(slice, self->size(), &i, &j, &step);
+ swig::setslice(self, i, j, v);
+ }
+
+ void __delitem__(PySliceObject *slice)
+ throw (std::out_of_range) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return;
+ }
+ PySlice_GetIndices(slice, self->size(), &i, &j, &step);
+ swig::delslice(self, i,j);
+ }
+
}
%enddef
diff --git a/Lib/python/pyerrors.swg b/Lib/python/pyerrors.swg
index e287e2fc8..01cf53e9b 100644
--- a/Lib/python/pyerrors.swg
+++ b/Lib/python/pyerrors.swg
@@ -58,12 +58,12 @@ SWIG_Python_AddErrorMsg(const char* mesg)
PyObject *old_str = PyObject_Str(value);
PyErr_Clear();
Py_XINCREF(type);
- PyErr_Format(type, "%s %s", PyString_AsString(old_str), mesg);
+
+ PyErr_Format(type, "%s %s",
+ SWIG_Python_str_AsChar(old_str), mesg);
Py_DECREF(old_str);
Py_DECREF(value);
} else {
PyErr_SetString(PyExc_RuntimeError, mesg);
}
}
-
-
diff --git a/Lib/python/pyhead.swg b/Lib/python/pyhead.swg
index 7839511bc..d73d3d112 100644
--- a/Lib/python/pyhead.swg
+++ b/Lib/python/pyhead.swg
@@ -1,3 +1,47 @@
+/* Compatibility marcos for Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+
+#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type)
+
+#define PyInt_Check(x) PyLong_Check(x)
+#define PyInt_AsLong(x) PyLong_AsLong(x)
+#define PyInt_FromLong(x) PyLong_FromLong(x)
+
+#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args)
+#endif
+
+#ifndef Py_TYPE
+# define Py_TYPE(op) ((op)->ob_type)
+#endif
+
+/* SWIG APIs for compatibility of boht Python 2 & 3 */
+
+#if PY_VERSION_HEX >= 0x03000000
+# define SWIG_Python_str_FromFormat PyUnicode_FromFormat
+#else
+# define SWIG_Python_str_FromFormat PyString_FromFormat
+#endif
+
+SWIGINTERN char*
+SWIG_Python_str_AsChar(PyObject *str)
+{
+#if PY_VERSION_HEX >= 0x03000000
+ str = PyUnicode_AsUTF8String(str);
+ return PyBytes_AsString(str);
+#else
+ return PyString_AsString(str);
+#endif
+}
+
+SWIGINTERN PyObject*
+SWIG_Python_str_FromChar(const char *c)
+{
+#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_FromString(c);
+#else
+ return PyString_FromString(c);
+#endif
+}
/* Add PyOS_snprintf for old Pythons */
#if PY_VERSION_HEX < 0x02020000
diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg
index e6109b7bd..ab55765ad 100644
--- a/Lib/python/pyinit.swg
+++ b/Lib/python/pyinit.swg
@@ -33,18 +33,48 @@ typedef struct swig_varlinkobject {
SWIGINTERN PyObject *
swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) {
+#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_InternFromString("<Swig global variables>");
+#else
return PyString_FromString("<Swig global variables>");
+#endif
}
SWIGINTERN PyObject *
swig_varlink_str(swig_varlinkobject *v) {
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject *str = PyUnicode_InternFromString("(");
+ PyObject *tail;
+ PyObject *joined;
+ swig_globalvar *var;
+ for (var = v->vars; var; var=var->next) {
+ tail = PyUnicode_FromString(var->name);
+ joined = PyUnicode_Concat(str, tail);
+ Py_DecRef(str);
+ Py_DecRef(tail);
+ str = joined;
+ if (var->next) {
+ tail = PyUnicode_InternFromString(", ");
+ joined = PyUnicode_Concat(str, tail);
+ Py_DecRef(str);
+ Py_DecRef(tail);
+ str = joined;
+ }
+ }
+ tail = PyUnicode_InternFromString(")");
+ joined = PyUnicode_Concat(str, tail);
+ Py_DecRef(str);
+ Py_DecRef(tail);
+ str = joined;
+#else
PyObject *str = PyString_FromString("(");
- swig_globalvar *var;
+ swig_globalvar *var;
for (var = v->vars; var; var=var->next) {
PyString_ConcatAndDel(&str,PyString_FromString(var->name));
if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", "));
}
PyString_ConcatAndDel(&str,PyString_FromString(")"));
+#endif
return str;
}
@@ -52,7 +82,7 @@ SWIGINTERN int
swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) {
PyObject *str = swig_varlink_str(v);
fprintf(fp,"Swig global variables ");
- fprintf(fp,"%s\n", PyString_AsString(str));
+ fprintf(fp,"%s\n", SWIG_Python_str_AsChar(str));
Py_DECREF(str);
return 0;
}
@@ -110,8 +140,13 @@ swig_varlink_type(void) {
if (!type_init) {
const PyTypeObject tmp
= {
+ /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
PyObject_HEAD_INIT(NULL)
0, /* Number of items in variable part (ob_size) */
+#endif
(char *)"swigvarlink", /* Type name (tp_name) */
sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */
0, /* Itemsize (tp_itemsize) */
@@ -147,7 +182,10 @@ swig_varlink_type(void) {
#endif
};
varlink_type = tmp;
+ /* for Python 3 we already assigned the ob_type in PyVarObject_HEAD_INIT() */
+#if PY_VERSION_HEX < 0x03000000
varlink_type.ob_type = &PyType_Type;
+#endif
type_init = 1;
}
return &varlink_type;
@@ -272,13 +310,35 @@ SWIG_Python_FixMethods(PyMethodDef *methods,
#ifdef __cplusplus
extern "C"
#endif
-SWIGEXPORT void SWIG_init(void) {
+
+SWIGEXPORT
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject*
+#else
+ void
+#endif
+SWIG_init(void) {
PyObject *m, *d;
/* Fix SwigMethods to carry the callback ptrs when needed */
SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
-
+#if PY_VERSION_HEX >= 0x03000000
+ static struct PyModuleDef SWIG_module = {
+ PyModuleDef_HEAD_INIT,
+ (char *) SWIG_name,
+ NULL,
+ -1,
+ SwigMethods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ m = PyModule_Create(&SWIG_module);
+#else
m = Py_InitModule((char *) SWIG_name, SwigMethods);
+#endif
d = PyModule_GetDict(m);
SWIG_InitializeModule(0);
diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg
index 38f1791a9..62a7eaf70 100644
--- a/Lib/python/pyiterators.swg
+++ b/Lib/python/pyiterators.swg
@@ -66,6 +66,12 @@ namespace swig {
return obj;
}
+ /* Make an alias for Python 3.x */
+ PyObject *__next__()
+ {
+ return next();
+ }
+
PyObject *previous()
{
SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads
@@ -335,6 +341,7 @@ namespace swig
%catches(swig::stop_iteration) PySwigIterator::decr(size_t n = 1);
%catches(std::invalid_argument) PySwigIterator::distance(const PySwigIterator &x) const;
%catches(std::invalid_argument) PySwigIterator::equal (const PySwigIterator &x) const;
+ %catches(swig::stop_iteration) PySwigIterator::__next__();
%catches(swig::stop_iteration) PySwigIterator::next();
%catches(swig::stop_iteration) PySwigIterator::previous();
%catches(swig::stop_iteration) PySwigIterator::advance(ptrdiff_t n);
@@ -370,6 +377,7 @@ namespace swig
virtual PySwigIterator *copy() const = 0;
PyObject *next();
+ PyObject *__next__();
PyObject *previous();
PySwigIterator *advance(ptrdiff_t n);
diff --git a/Lib/python/pyopers.swg b/Lib/python/pyopers.swg
index 76f1e6789..bd5c954f0 100644
--- a/Lib/python/pyopers.swg
+++ b/Lib/python/pyopers.swg
@@ -33,6 +33,12 @@
/* Special cases */
%rename(__invert__) *::operator~;
%rename(__call__) *::operator();
+
+%feature("shadow") *::operator bool %{
+def __nonzero__(self):
+ return $action(self)
+__bool__ = __nonzero__
+%};
%rename(__nonzero__) *::operator bool;
/* Ignored operators */
diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg
index 844a66bec..4f51d3a95 100644
--- a/Lib/python/pyrun.swg
+++ b/Lib/python/pyrun.swg
@@ -348,9 +348,13 @@ PySwigObject_format(const char* fmt, PySwigObject *v)
PyObject *args = PyTuple_New(1);
if (args) {
if (PyTuple_SetItem(args, 0, PySwigObject_long(v)) == 0) {
- PyObject *ofmt = PyString_FromString(fmt);
+ PyObject *ofmt = SWIG_Python_str_FromChar(fmt);
if (ofmt) {
+#if PY_VERSION_HEX >= 0x03000000
+ res = PyUnicode_Format(ofmt,args);
+#else
res = PyString_Format(ofmt,args);
+#endif
Py_DECREF(ofmt);
}
Py_DECREF(args);
@@ -380,7 +384,7 @@ PySwigObject_repr(PySwigObject *v, PyObject *args)
{
const char *name = SWIG_TypePrettyName(v->ty);
PyObject *hex = PySwigObject_hex(v);
- PyObject *repr = PyString_FromFormat("<Swig Object of type '%s' at 0x%s>", name, PyString_AsString(hex));
+ PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at 0x%U>", name, hex);
Py_DECREF(hex);
if (v->next) {
#ifdef METH_NOARGS
@@ -388,7 +392,14 @@ PySwigObject_repr(PySwigObject *v, PyObject *args)
#else
PyObject *nrep = PySwigObject_repr((PySwigObject *)v->next, args);
#endif
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject *joined = PyUnicode_Concat(repr, nrep);
+ Py_DecRef(repr);
+ Py_DecRef(nrep);
+ repr = joined;
+#else
PyString_ConcatAndDel(&repr,nrep);
+#endif
}
return repr;
}
@@ -402,7 +413,7 @@ PySwigObject_print(PySwigObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
PyObject *repr = PySwigObject_repr(v, NULL);
#endif
if (repr) {
- fputs(PyString_AsString(repr), fp);
+ fputs(SWIG_Python_str_AsChar(repr), fp);
Py_DECREF(repr);
return 0;
} else {
@@ -415,7 +426,7 @@ PySwigObject_str(PySwigObject *v)
{
char result[SWIG_BUFFER_SIZE];
return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
- PyString_FromString(result) : 0;
+ SWIG_Python_str_FromChar(result) : 0;
}
SWIGRUNTIME int
@@ -426,6 +437,24 @@ PySwigObject_compare(PySwigObject *v, PySwigObject *w)
return (i < j) ? -1 : ((i > j) ? 1 : 0);
}
+/* Added for Python 3.x, whould it also useful for Python 2.x? */
+SWIGRUNTIME PyObject*
+PySwigObject_richcompare(PySwigObject *v, PySwigObject *w, int op)
+{
+ PyObject* res;
+ if( op != Py_EQ && op != Py_NE ) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ if( (PySwigObject_compare(v, w)==0) == (op == Py_EQ) )
+ res = Py_True;
+ else
+ res = Py_False;
+ Py_INCREF(res);
+ return res;
+}
+
+
SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
SWIGRUNTIME PyTypeObject*
@@ -436,8 +465,8 @@ PySwigObject_type(void) {
SWIGRUNTIMEINLINE int
PySwigObject_Check(PyObject *op) {
- return ((op)->ob_type == PySwigObject_type())
- || (strcmp((op)->ob_type->tp_name,"PySwigObject") == 0);
+ return (Py_TYPE(op) == PySwigObject_type())
+ || (strcmp(Py_TYPE(op)->tp_name,"PySwigObject") == 0);
}
SWIGRUNTIME PyObject *
@@ -610,7 +639,10 @@ _PySwigObject_type(void) {
(binaryfunc)0, /*nb_add*/
(binaryfunc)0, /*nb_subtract*/
(binaryfunc)0, /*nb_multiply*/
+ /* nb_divide removed in Python 3 */
+#if PY_VERSION_HEX < 0x03000000
(binaryfunc)0, /*nb_divide*/
+#endif
(binaryfunc)0, /*nb_remainder*/
(binaryfunc)0, /*nb_divmod*/
(ternaryfunc)0,/*nb_power*/
@@ -624,13 +656,19 @@ _PySwigObject_type(void) {
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
- (coercion)0, /*nb_coerce*/
+#if PY_VERSION_HEX < 0x03000000
+ 0, /*nb_coerce*/
+#endif
(unaryfunc)PySwigObject_long, /*nb_int*/
(unaryfunc)PySwigObject_long, /*nb_long*/
(unaryfunc)0, /*nb_float*/
+#if PY_VERSION_HEX < 0x03000000
(unaryfunc)PySwigObject_oct, /*nb_oct*/
(unaryfunc)PySwigObject_hex, /*nb_hex*/
-#if PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
+#endif
+#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
+#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */
@@ -644,8 +682,13 @@ _PySwigObject_type(void) {
if (!type_init) {
const PyTypeObject tmp
= {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
+ /* PyOjbect header changed in Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+#endif
(char *)"PySwigObject", /* tp_name */
sizeof(PySwigObject), /* tp_basicsize */
0, /* tp_itemsize */
@@ -672,7 +715,7 @@ _PySwigObject_type(void) {
swigobject_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
- 0, /* tp_richcompare */
+ (richcmpfunc)PySwigObject_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
#if PY_VERSION_HEX >= 0x02020000
0, /* tp_iter */
@@ -704,7 +747,10 @@ _PySwigObject_type(void) {
#endif
};
pyswigobject_type = tmp;
+ /* for Python 3 we already assigned the ob_type in PyVarObject_HEAD_INIT() */
+#if PY_VERSION_HEX < 0x03000000
pyswigobject_type.ob_type = &PyType_Type;
+#endif
type_init = 1;
}
return &pyswigobject_type;
@@ -753,9 +799,9 @@ PySwigPacked_repr(PySwigPacked *v)
{
char result[SWIG_BUFFER_SIZE];
if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
- return PyString_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
+ return SWIG_Python_str_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
} else {
- return PyString_FromFormat("<Swig Packed %s>", v->ty->name);
+ return SWIG_Python_str_FromFormat("<Swig Packed %s>", v->ty->name);
}
}
@@ -764,9 +810,9 @@ PySwigPacked_str(PySwigPacked *v)
{
char result[SWIG_BUFFER_SIZE];
if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){
- return PyString_FromFormat("%s%s", result, v->ty->name);
+ return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name);
} else {
- return PyString_FromString(v->ty->name);
+ return SWIG_Python_str_FromChar(v->ty->name);
}
}
@@ -811,8 +857,13 @@ _PySwigPacked_type(void) {
if (!type_init) {
const PyTypeObject tmp
= {
+ /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX>=0x03000000
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
+ 0, /* ob_size */
+#endif
(char *)"PySwigPacked", /* tp_name */
sizeof(PySwigPacked), /* tp_basicsize */
0, /* tp_itemsize */
@@ -867,7 +918,10 @@ _PySwigPacked_type(void) {
#endif
};
pyswigpacked_type = tmp;
+ /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
+#if PY_VERSION_HEX < 0x03000000
pyswigpacked_type.ob_type = &PyType_Type;
+#endif
type_init = 1;
}
return &pyswigpacked_type;
@@ -912,7 +966,7 @@ PySwigPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
SWIGRUNTIMEINLINE PyObject *
_SWIG_This(void)
{
- return PyString_FromString("this");
+ return SWIG_Python_str_FromChar("this");
}
SWIGRUNTIME PyObject *
@@ -924,6 +978,11 @@ SWIG_This(void)
/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
+/* TODO: I don't know how to implement the fast getset in Python 3 right now */
+#if PY_VERSION_HEX>=0x03000000
+#define SWIG_PYTHON_SLOW_GETSET_THIS
+#endif
+
SWIGRUNTIME PySwigObject *
SWIG_Python_GetSwigThis(PyObject *pyobj)
{
@@ -1161,10 +1220,17 @@ SWIG_Python_NewShadowInstance(PySwigClientData *data, PyObject *swig_this)
#endif
}
} else {
+#if PY_VERSION_HEX >= 0x03000000
+ inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+ Py_INCREF(data->newargs);
+ PyObject_SetAttr(inst, SWIG_This(), swig_this);
+ Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+#else
PyObject *dict = PyDict_New();
PyDict_SetItem(dict, SWIG_This(), swig_this);
inst = PyInstance_NewRaw(data->newargs, dict);
Py_DECREF(dict);
+#endif
}
return inst;
#else
@@ -1344,8 +1410,13 @@ SWIGRUNTIME void
SWIG_Python_SetModule(swig_module_info *swig_module) {
static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
+#if PY_VERSION_HEX >= 0x03000000
+ /* Add a dummy module object into sys.modules */
+ PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+#else
PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
swig_empty_runtime_method_table);
+#endif
PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
if (pointer && module) {
PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
@@ -1365,7 +1436,7 @@ SWIGRUNTIME swig_type_info *
SWIG_Python_TypeQuery(const char *type)
{
PyObject *cache = SWIG_Python_TypeCache();
- PyObject *key = PyString_FromString(type);
+ PyObject *key = SWIG_Python_str_FromChar(type);
PyObject *obj = PyDict_GetItem(cache, key);
swig_type_info *descriptor;
if (obj) {
@@ -1403,9 +1474,9 @@ SWIG_Python_AddErrMesg(const char* mesg, int infront)
Py_XINCREF(type);
PyErr_Clear();
if (infront) {
- PyErr_Format(type, "%s %s", mesg, PyString_AsString(old_str));
+ PyErr_Format(type, "%s %s", mesg, SWIG_Python_str_AsChar(old_str));
} else {
- PyErr_Format(type, "%s %s", PyString_AsString(old_str), mesg);
+ PyErr_Format(type, "%s %s", SWIG_Python_str_AsChar(old_str), mesg);
}
Py_DECREF(old_str);
}
@@ -1454,7 +1525,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
const char *otype = (obj ? obj->ob_type->tp_name : 0);
if (otype) {
PyObject *str = PyObject_Str(obj);
- const char *cstr = str ? PyString_AsString(str) : 0;
+ const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0;
if (cstr) {
PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
type, otype, cstr);
diff --git a/Lib/python/pystrings.swg b/Lib/python/pystrings.swg
index d4d60c42b..5a06792d7 100644
--- a/Lib/python/pystrings.swg
+++ b/Lib/python/pystrings.swg
@@ -5,10 +5,20 @@
SWIGINTERN int
SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
{
- if (PyString_Check(obj)) {
+%#if PY_VERSION_HEX>=0x03000000
+ if (PyUnicode_Check(obj))
+%#else
+ if (PyString_Check(obj))
+%#endif
+ {
char *cstr; Py_ssize_t len;
+%#if PY_VERSION_HEX>=0x03000000
+ obj = PyUnicode_AsUTF8String(obj);
+ PyBytes_AsStringAndSize(obj, &cstr, &len);
+%#else
PyString_AsStringAndSize(obj, &cstr, &len);
- if (cptr) {
+%#endif
+ if (cptr) {
if (alloc) {
/*
In python the user should not be able to modify the inner
@@ -33,7 +43,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
*alloc = SWIG_OLDOBJ;
}
} else {
- *cptr = PyString_AsString(obj);
+ *cptr = SWIG_Python_str_AsChar(obj);
}
}
if (psize) *psize = len + 1;
@@ -64,7 +74,11 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
return pchar_descriptor ?
SWIG_NewPointerObj(%const_cast(carray,char *), pchar_descriptor, 0) : SWIG_Py_Void();
} else {
+%#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_FromStringAndSize(carray, %numeric_cast(size,int));
+%#else
return PyString_FromStringAndSize(carray, %numeric_cast(size,int));
+%#endif
}
} else {
return SWIG_Py_Void();
diff --git a/Lib/python/pywstrings.swg b/Lib/python/pywstrings.swg
index 8254bf8f7..4161dcb0f 100644
--- a/Lib/python/pywstrings.swg
+++ b/Lib/python/pywstrings.swg
@@ -8,12 +8,14 @@ SWIG_AsWCharPtrAndSize(PyObject *obj, wchar_t **cptr, size_t *psize, int *alloc)
{
PyObject *tmp = 0;
int isunicode = PyUnicode_Check(obj);
+%#if PY_VERSION_HEX < 0x03000000
if (!isunicode && PyString_Check(obj)) {
if (cptr) {
obj = tmp = PyUnicode_FromObject(obj);
}
isunicode = 1;
}
+%#endif
if (isunicode) {
int len = PyUnicode_GetSize(obj);
if (cptr) {
diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i
index 12dc23ccf..b080731f0 100644
--- a/Lib/python/std_map.i
+++ b/Lib/python/std_map.i
@@ -22,6 +22,10 @@
int res = SWIG_ERROR;
if (PyDict_Check(obj)) {
PyObject_var items = PyObject_CallMethod(obj,(char *)"items",NULL);
+%#if PY_VERSION_HEX >= 0x03000000
+ /* In Python 3.x the ".items()" method return a dict_items object */
+ items = PySequence_Fast(items, ".items() havn't returned a sequence!");
+%#endif
res = traits_asptr_stdseq<std::map<K,T>, std::pair<K, T> >::asptr(items, val);
} else {
map_type *p;
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index 032c71f7e..871565df8 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -690,7 +690,15 @@ int yylex(void) {
termtoken = SWIG_TOKEN_LPAREN;
termvalue = "(";
break;
- } else if (nexttok == SWIG_TOKEN_SEMI) {
+ } else if (nexttok == SWIG_TOKEN_CODEBLOCK) {
+ termtoken = SWIG_TOKEN_CODEBLOCK;
+ termvalue = Scanner_text(scan);
+ break;
+ } else if (nexttok == SWIG_TOKEN_LBRACE) {
+ termtoken = SWIG_TOKEN_LBRACE;
+ termvalue = "{";
+ break;
+ } else if (nexttok == SWIG_TOKEN_SEMI) {
termtoken = SWIG_TOKEN_SEMI;
termvalue = ";";
break;
@@ -859,8 +867,14 @@ int yylex(void) {
return (INLINE);
if (strcmp(yytext, "%typemap") == 0)
return (TYPEMAP);
- if (strcmp(yytext, "%feature") == 0)
+ if (strcmp(yytext, "%feature") == 0) {
+ /* The rename_active indicates we don't need the information of the
+ * following function's return type. This applied for %rename, so do
+ * %feature.
+ */
+ rename_active = 1;
return (FEATURE);
+ }
if (strcmp(yytext, "%except") == 0)
return (EXCEPT);
if (strcmp(yytext, "%importfile") == 0)
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 58e0c0c41..69c2a503d 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -2290,21 +2290,25 @@ feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbr
String *val = $7 ? NewString($7) : NewString("1");
new_feature($3, val, 0, $5.id, $5.type, $5.parms, $6.qualifier);
$$ = 0;
+ scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum RPAREN declarator cpp_const SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, 0, $7.id, $7.type, $7.parms, $8.qualifier);
$$ = 0;
+ scanner_clear_rename();
}
| FEATURE LPAREN idstring featattr RPAREN declarator cpp_const stringbracesemi {
String *val = $8 ? NewString($8) : NewString("1");
new_feature($3, val, $4, $6.id, $6.type, $6.parms, $7.qualifier);
$$ = 0;
+ scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum featattr RPAREN declarator cpp_const SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, $6, $8.id, $8.type, $8.parms, $9.qualifier);
$$ = 0;
+ scanner_clear_rename();
}
/* Global feature */
@@ -2312,21 +2316,25 @@ feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbr
String *val = $5 ? NewString($5) : NewString("1");
new_feature($3, val, 0, 0, 0, 0, 0);
$$ = 0;
+ scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum RPAREN SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, 0, 0, 0, 0, 0);
$$ = 0;
+ scanner_clear_rename();
}
| FEATURE LPAREN idstring featattr RPAREN stringbracesemi {
String *val = $6 ? NewString($6) : NewString("1");
new_feature($3, val, $4, 0, 0, 0, 0);
$$ = 0;
+ scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum featattr RPAREN SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, $6, 0, 0, 0, 0);
$$ = 0;
+ scanner_clear_rename();
}
;
diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
index ddd23d1f3..7a878b4f8 100644
--- a/Source/Modules/python.cxx
+++ b/Source/Modules/python.cxx
@@ -49,10 +49,11 @@ static String *shadow_indent = 0;
static int in_class = 0;
static int classic = 0;
static int modern = 0;
-static int apply = 0;
static int new_repr = 1;
static int no_header_file = 0;
+static int py3 = 0;
+
/* C++ Support + Shadow Classes */
static int have_constructor;
@@ -96,7 +97,6 @@ enum autodoc_t {
static const char *usage1 = (char *) "\
Python Options (available with -python)\n\
-aliasobj0 - Alias obj0 when using fastunpack, needed for some old typemaps \n\
- -apply - Use apply() in proxy classes\n\
-buildnone - Use Py_BuildValue(" ") to obtain Py_None (default in Windows)\n\
-castmode - Enable the casting mode, which allows implicit cast between types in python\n\
-classic - Use classic classes only\n\
@@ -148,6 +148,8 @@ static const char *usage3 = (char *) "\
-O - Enable all the optimization options: \n\
-modern -fastdispatch -dirvtable -nosafecstrings -fvirtual -noproxydel \n\
-fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone \n\
+ -py3 - Generate code with Python 3 specific features:\n\
+ Function annotation \n\
\n";
class PYTHON:public Language {
@@ -259,9 +261,6 @@ public:
} else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
shadow = 1;
Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-apply") == 0) {
- apply = 1;
- Swig_mark_arg(i);
} else if ((strcmp(argv[i], "-new_repr") == 0) || (strcmp(argv[i], "-newrepr") == 0)) {
new_repr = 1;
Swig_mark_arg(i);
@@ -284,7 +283,6 @@ public:
} else if (strcmp(argv[i], "-classic") == 0) {
classic = 1;
modernargs = 0;
- apply = 1;
modern = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-cppcast") == 0) {
@@ -390,7 +388,6 @@ public:
proxydel = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-modern") == 0) {
- apply = 0;
classic = 0;
modern = 1;
modernargs = 1;
@@ -408,7 +405,6 @@ public:
no_header_file = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-O") == 0) {
- apply = 0;
classic = 0;
modern = 1;
dirvtable = 1;
@@ -429,8 +425,17 @@ public:
fputs(usage1, stdout);
fputs(usage2, stdout);
fputs(usage3, stdout);
- }
+ } else if (strcmp(argv[i], "-py3") == 0) {
+ py3 = 1;
+ Swig_mark_arg(i);
+ }
+
}
+ } /* for */
+
+ if (py3) {
+ /* force disable features that not compatible with Python 3.x */
+ classic = 0;
}
if (cppcast) {
@@ -691,6 +696,13 @@ public:
Printv(f_shadow, "\nfrom sys import version_info\n", NULL);
+ if(fastproxy)
+ {
+ Printv(f_shadow, "if version_info >= (3,0,0):\n", NULL);
+ Printf(f_shadow, tab4 "new_instancemethod = lambda func, inst, cls: %s.SWIG_PyInstanceMethod_New(func)\n", module);
+ Printv(f_shadow, "else:\n", NULL);
+ Printv(f_shadow, tab4, "from new import instancemethod as new_instancemethod\n", NULL);
+ }
/* Import the C-extension module. This should be a relative import,
* since the shadow module may also have been imported by a relative
* import, and there is thus no guarantee that the C-extension is on
@@ -719,11 +731,9 @@ public:
* module. */
Printv(f_shadow, "del version_info\n", NULL);
- Printv(f_shadow, "import new\n", NULL);
- Printv(f_shadow, "new_instancemethod = new.instancemethod\n", NULL);
if (modern || !classic) {
Printv(f_shadow, "try:\n", tab4, "_swig_property = property\n", "except NameError:\n", tab4, "pass # Python < 2.2 doesn't have 'property'.\n", NULL);
- }
+ }
/* if (!modern) */
/* always needed, a class can be forced to be no-modern, such as an exception */
{
@@ -750,7 +760,7 @@ public:
"def _swig_getattr(self,class_type,name):\n",
tab4, "if (name == \"thisown\"): return self.this.own()\n",
tab4, "method = class_type.__swig_getmethods__.get(name,None)\n",
- tab4, "if method: return method(self)\n", tab4, "raise AttributeError,name\n\n", NIL);
+ tab4, "if method: return method(self)\n", tab4, "raise AttributeError(name)\n\n", NIL);
Printv(f_shadow,
"def _swig_repr(self):\n",
@@ -758,11 +768,17 @@ public:
tab4, "except: strthis = \"\"\n", tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL);
if (!classic) {
+ /* Usage of types.ObjectType is deprecated.
+ * But don't sure wether this would broken old Python?
+ */
Printv(f_shadow,
- "import types\n",
+// "import types\n",
"try:\n",
- " _object = types.ObjectType\n",
- " _newclass = 1\n", "except AttributeError:\n", " class _object : pass\n", " _newclass = 0\n", "del types\n", "\n\n", NIL);
+// " _object = types.ObjectType\n",
+ " _object = object\n",
+ " _newclass = 1\n", "except AttributeError:\n", " class _object : pass\n", " _newclass = 0\n",
+// "del types\n",
+ "\n\n", NIL);
}
}
if (modern) {
@@ -788,7 +804,11 @@ public:
}
- Printf(f_header, "#define SWIG_init init%s\n\n", module);
+ Printf(f_header, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_header, "# define SWIG_init PyInit_%s\n\n", module);
+ Printf(f_header, "#else\n");
+ Printf(f_header, "# define SWIG_init init%s\n\n", module);
+ Printf(f_header, "#endif\n");
Printf(f_header, "#define SWIG_name \"%s\"\n", module);
Printf(f_wrappers, "#ifdef __cplusplus\n");
@@ -797,6 +817,9 @@ public:
Append(const_code, "static swig_const_info swig_const_table[] = {\n");
Append(methods, "static PyMethodDef SwigMethods[] = {\n");
+ /* the method exported for replacement of new.instancemethod in Python 3 */
+ add_pyinstancemethod_new();
+
/* emit code */
Language::top(n);
@@ -815,6 +838,12 @@ public:
Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n");
Printf(f_wrappers, "%s\n", const_code);
initialize_threads(f_init);
+
+ Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_init, " return m;\n");
+ Printf(f_init, "#else\n");
+ Printf(f_init, " return;\n");
+ Printf(f_init, "#endif\n");
Printf(f_init, "}\n");
Printf(f_wrappers, "#ifdef __cplusplus\n");
@@ -822,10 +851,6 @@ public:
Printf(f_wrappers, "#endif\n");
if (shadow) {
- /*
- Printf(f_shadow_imports,"\nimport %s\n", module);
- Printv(f_shadow_py, f_shadow_imports, "\n",NIL);
- */
Printv(f_shadow_py, f_shadow, "\n", NIL);
Printv(f_shadow_py, f_shadow_stubs, "\n", NIL);
@@ -859,6 +884,19 @@ public:
return SWIG_OK;
}
+
+ /* ------------------------------------------------------------
+ * Emit the wrapper for PyInstanceMethod_New to MethodDef array.
+ * This wrapper is used to implement -fastproxy,
+ * as a replacement of new.instancemethod in Python 3.
+ * ------------------------------------------------------------ */
+ int add_pyinstancemethod_new()
+ {
+ String* name = NewString("SWIG_PyInstanceMethod_New");
+ Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_O, NULL},", name, name);
+ Delete(name);
+ return 0;
+ }
/* ------------------------------------------------------------
* importDirective()
@@ -902,25 +940,19 @@ public:
return Language::importDirective(n);
}
-
/* ------------------------------------------------------------
- * emitFuncCallHelper()
- * Write the shadow code to call a function in the extension
- * module. Takes into account the -apply flag and whether
- * to use keyword args or not.
+ * funcCall()
+ * Emit shadow code to call a function in the extension
+ * module. Using proper argument and calling style for
+ * given node n.
* ------------------------------------------------------------ */
+ String *funcCall(String *name, String *parms) {
+ String *str = NewString("");
- String *funcCallHelper(String *name, int kw) {
- String *str;
-
- str = NewString("");
- if (apply) {
- Printv(str, "apply(", module, ".", name, ", args", (kw ? ", kwargs" : ""), ")", NIL);
- } else {
- Printv(str, module, ".", name, "(*args", (kw ? ", **kwargs" : ""), ")", NIL);
- }
+ Printv(str, module, ".", name, "(", parms, ")", NIL);
return str;
- }
+ }
+
/* ------------------------------------------------------------
* pythoncode() - Output python code into the shadow file
@@ -1088,29 +1120,84 @@ public:
return doc;
}
+ /* -----------------------------------------------------------------------------
+ * makeParameterName()
+ * Note: the generated name should consist with that in kwnames[]
+ *
+ * Inputs:
+ * n - Node
+ * p - parameter node
+ * arg_num - parameter argument number
+ * Return:
+ * arg - a unique parameter name
+ * ----------------------------------------------------------------------------- */
+
+ String *makeParameterName(ParmList *plist, Parm *p, int arg_num) {
+ String *arg = 0;
+ String *pn = Swig_name_make(p, 0, Getattr(p, "name"), 0, 0);
+ // Use C parameter name unless it is a duplicate or an empty parameter name
+ int count = 0;
+ if ( SwigType_isvarargs(Getattr(p, "type")) ) {
+ return NewString("*args");
+ }
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+ arg = (!pn || !Len(pn) || (count > 1)) ? NewStringf("arg%d", arg_num) : Copy(pn);
+ return arg;
+ }
+
+
/* ------------------------------------------------------------
* make_autodocParmList()
* Generate the documentation for the function parameters
+ * Parameters:
+ * func_annotation: Function annotation support
* ------------------------------------------------------------ */
- String *make_autodocParmList(Node *n, bool showTypes) {
+ String *make_autodocParmList(Node *n, bool showTypes, bool calling=false, bool func_annotation=false) {
+
+
String *doc = NewString("");
String *pdocs = Copy(Getattr(n, "feature:pdocs"));
ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p;
Parm *pnext;
- Node *lookup;
+ Node *lookup;
+
+
int lines = 0;
+ int arg_num = 0;
const int maxwidth = 50;
+ if(calling)
+ func_annotation = false;
+
if (pdocs)
Append(pdocs, "\n");
-
Swig_typemap_attach_parms("in", plist, 0);
Swig_typemap_attach_parms("doc", plist, 0);
-
+
+ if (Strcmp(ParmList_protostr(plist), "void")==0) {
+ //No parameters actually
+ return doc;
+ }
+
for (p = plist; p; p = pnext) {
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
String *name = 0;
String *type = 0;
String *value = 0;
@@ -1127,12 +1214,14 @@ public:
type = type ? type : Getattr(p, "type");
value = value ? value : Getattr(p, "value");
- String *tm = Getattr(p, "tmap:in");
- if (tm) {
- pnext = Getattr(p, "tmap:in:next");
- } else {
- pnext = nextSibling(p);
- }
+ name = makeParameterName(plist, p, arg_num);
+ // Reset it for convinient in further use. (mainly for makeParameterName())
+ // Since the plist is created by CopyParmList,
+ // we can hope that the set would have no side effect
+ Setattr(p, "name", name);
+
+ arg_num++;
+
if (Len(doc)) {
// add a comma to the previous one if any
@@ -1144,39 +1233,40 @@ public:
lines += 1;
}
}
+
+ type = SwigType_base(type);
+ lookup = Swig_symbol_clookup(type, 0);
+ if (lookup)
+ type = Getattr(lookup, "sym:name");
+
// Do the param type too?
- if (showTypes) {
- type = SwigType_base(type);
- lookup = Swig_symbol_clookup(type, 0);
- if (lookup)
- type = Getattr(lookup, "sym:name");
- Printf(doc, "%s ", type);
- }
-
- if (name) {
- Append(doc, name);
- if (pdoc) {
- if (!pdocs)
- pdocs = NewString("Parameters:\n");
- Printf(pdocs, " %s\n", pdoc);
- }
- } else {
- Append(doc, "?");
+ if (showTypes)
+ Printf(doc, "%s ", type);
+
+
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ pdocs = NewString("Parameters:\n");
+ Printf(pdocs, " %s\n", pdoc);
}
- if (value) {
- if (Strcmp(value, "NULL") == 0)
- value = NewString("None");
- else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0)
- value = NewString("True");
- else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0)
- value = NewString("False");
+ // Write the function annoation
+ if (func_annotation)
+ Printf(doc, " : '%s'", type);
+
+ // Write default value
+ if (value && !calling) {
+ String* pv = pyvalue(value, Getattr(p, "type"));
+ if (pv)
+ value = pv;
else {
lookup = Swig_symbol_clookup(value, 0);
- if (lookup)
+ if (lookup) {
value = Getattr(lookup, "sym:name");
+ }
}
- Printf(doc, "=%s", value);
+ Printf(doc, " = %s", value);
}
}
if (pdocs)
@@ -1314,6 +1404,132 @@ public:
return doc;
}
+
+ /* ------------------------------------------------------------
+ * pyvalue()
+ * Check if string v can be a Python value literal,
+ * (eg. number or string), or translate it to a Python literal.
+ * ------------------------------------------------------------ */
+ String* pyvalue(String *v, SwigType *t)
+ {
+ if (v && Len(v)>0) {
+ char fc = (Char(v))[0];
+ if (('0'<=fc && fc<='9') || '\''==fc || '"'==fc) {
+ /* number or string (or maybe NULL pointer)*/
+ if (SwigType_ispointer(t) && Strcmp(v, "0")==0)
+ return NewString("None");
+ else
+ return v;
+ }
+ if (Strcmp(v, "true")==0 || Strcmp(v, "FALSE")==0)
+ return NewString("True");
+ if (Strcmp(v, "false")==0 || Strcmp(v, "FALSE")==0)
+ return NewString("False");
+ if (Strcmp(v, "NULL")==0)
+ return NewString("None");
+ }
+ return 0;
+ }
+ /* ------------------------------------------------------------
+ * is_primitive_defaultargs()
+ * Check if all the default args have primitive type.
+ * (So we can generate proper parameter list with default
+ * values..)
+ * ------------------------------------------------------------ */
+ bool is_primitive_defaultargs(Node *n)
+ {
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ for (p = plist; p; p = pnext) {
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+ String *type = Getattr(p, "type");
+ String *value = Getattr(p, "value");
+ if (!pyvalue(value, type))
+ return false;
+ }
+ return true;
+ }
+
+
+ /* ------------------------------------------------------------
+ * is_real_overloaded()
+ * Check if the function is overloaded, but not just have some
+ * siblings generated due to the original function have
+ * default arguments.
+ * ------------------------------------------------------------ */
+ bool is_real_overloaded(Node *n)
+ {
+ Node *h = Getattr(n, "sym:overloaded");
+ Node *i;
+ if (!h)
+ return false;
+
+ i = Getattr(h, "sym:nextSibling");
+ while (i) {
+ Node *nn = Getattr(i, "defaultargs");
+ if (nn != h) {
+ /* Check if overloaded function has defaultargs and
+ * pointed to the first overloaded. */
+ return true;
+ }
+ i = Getattr(i, "sym:nextSibling");
+ }
+
+ return false;
+ }
+
+ /* ------------------------------------------------------------
+ * make_pyParmList()
+ * Generate parameter list for Python functions or methods,
+ * reuse make_autodocParmList() to do so.
+ * ------------------------------------------------------------ */
+ String* make_pyParmList(Node *n, bool in_class, bool is_calling, int kw)
+ {
+ /* Get the original function for a defaultargs copy,
+ * see default_arguments() in parser.y. */
+ Node *nn = Getattr(n, "defaultargs");
+ if (nn) n = nn;
+
+ /* For overloaded function, just use *args */
+ if (is_real_overloaded(n) ||
+ GetFlag(n, "feature:compactdefaultargs") ||
+ !is_primitive_defaultargs(n))
+ {
+ String *parms = NewString("");
+ if(in_class)
+ Printf(parms, "self, ");
+ Printf(parms, "*args");
+ if (kw)
+ Printf(parms, ", **kwargs");
+ return parms;
+ }
+
+ bool funcanno = py3 ? true : false;
+ String *params = NewString("");
+ String *_params = make_autodocParmList(n, false, is_calling, funcanno);
+
+ if (in_class)
+ {
+ Printf(params, "self");
+ if(Len(_params) > 0)
+ Printf(params, ", ");
+ }
+
+ Printv(params, _params, NULL);
+
+ return params;
+ }
/* ------------------------------------------------------------
* have_pythonprepend()
@@ -1379,6 +1595,40 @@ public:
return have_pythonappend(n) || have_pythonprepend(n) || have_docstring(n);
}
+
+ /* ------------------------------------------------------------
+ * returnTypeAnnotation()
+ * Helper function for constructing the function annotation
+ * of the returning type, return a empty string for Python 2.x
+ * ------------------------------------------------------------ */
+ String* returnTypeAnnotation(Node *n)
+ {
+ String *ret=0;
+ Parm *p = Getattr(n, "parms");
+ String *tm;
+ /* Try to guess the returning type by argout typemap,
+ * however the result may not accurate. */
+ while (p) {
+ if ((tm=Getattr(p, "tmap:argout:match_type"))) {
+ tm = SwigType_str(tm, 0);
+ if (ret)
+ Printv(ret, ", ", tm, NULL);
+ else
+ ret = tm;
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ /* If no argout typemap, then get the returning type from
+ * the function prototype. */
+ if (!ret) {
+ ret = Getattr(n, "type");
+ if (ret) ret = SwigType_str(ret, 0);
+ }
+ return (ret && py3) ? NewStringf(" -> \"%s\" ", ret)
+ : NewString("");
+ }
/* ------------------------------------------------------------
* emitFunctionShadowHelper()
@@ -1388,24 +1638,26 @@ public:
* ------------------------------------------------------------ */
void emitFunctionShadowHelper(Node *n, File *f_dest, String *name, int kw) {
- if (Getattr(n, "feature:python:callback") || !have_addtofunc(n)) {
- /* If there is no addtofunc directive then just assign from the extension module */
- Printv(f_dest, name, " = ", module, ".", name, "\n", NIL);
+ String *parms = make_pyParmList(n, false, false, kw);
+ String *callParms = make_pyParmList(n, false, true, kw);
+ /* Make a wrapper function to insert the code into */
+ Printv(f_dest, "\ndef ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (have_docstring(n))
+ Printv(f_dest, ctab4, docstring(n, AUTODOC_FUNC, tab4), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_dest, ctab4, pythonprepend(n), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_dest, ctab4, "val = ", funcCall(name, callParms), "\n", NIL);
+ Printv(f_dest, ctab4, pythonappend(n), "\n", NIL);
+ Printv(f_dest, ctab4, "return val\n", NIL);
} else {
- /* Otherwise make a wrapper function to insert the code into */
- Printv(f_dest, "\ndef ", name, "(*args", (kw ? ", **kwargs" : ""), "):\n", NIL);
- if (have_docstring(n))
- Printv(f_dest, ctab4, docstring(n, AUTODOC_FUNC, tab4), "\n", NIL);
- if (have_pythonprepend(n))
- Printv(f_dest, ctab4, pythonprepend(n), "\n", NIL);
- if (have_pythonappend(n)) {
- Printv(f_dest, ctab4, "val = ", funcCallHelper(name, kw), "\n", NIL);
- Printv(f_dest, ctab4, pythonappend(n), "\n", NIL);
- Printv(f_dest, ctab4, "return val\n", NIL);
- } else {
- Printv(f_dest, ctab4, "return ", funcCallHelper(name, kw), "\n", NIL);
- }
+ Printv(f_dest, ctab4, "return ", funcCall(name, callParms), "\n", NIL);
}
+
+ if (Getattr(n, "feature:python:callback") || !have_addtofunc(n)) {
+ /* If there is no addtofunc directive then just assign from the extension module (for speed up) */
+ Printv(f_dest, name, " = ", module, ".", name, "\n", NIL);
+ }
}
@@ -2488,7 +2740,7 @@ public:
Printf(f_directors_h, " PyObject *swig_get_method(size_t method_index, const char *method_name) const {\n");
Printf(f_directors_h, " PyObject *method = vtable[method_index];\n");
Printf(f_directors_h, " if (!method) {\n");
- Printf(f_directors_h, " swig::PyObject_var name = PyString_FromString(method_name);\n");
+ Printf(f_directors_h, " swig::PyObject_var name = SWIG_Python_str_FromChar(method_name);\n");
Printf(f_directors_h, " method = PyObject_GetAttr(swig_get_self(), name);\n");
Printf(f_directors_h, " if (method == NULL) {\n");
Printf(f_directors_h, " std::string msg = \"Method in class %s doesn't exist, undefined \";\n", classname);
@@ -2623,6 +2875,16 @@ public:
}
}
}
+
+ /* dealing with abstract base class */
+ String *abcs = Getattr(n, "feature:python:abc");
+ if (py3 && abcs) {
+ if (Len(base_class)) {
+ Putc(',', base_class);
+ }
+ Printv(base_class, abcs, NIL);
+ }
+
Printv(f_shadow, "class ", class_name, NIL);
if (Len(base_class)) {
@@ -2631,6 +2893,9 @@ public:
if (!classic) {
Printf(f_shadow, modern ? "(object)" : "(_object)");
}
+ if (GetFlag(n, "feature:exceptionclass") ) {
+ Printf(f_shadow, "(Exception)");
+ }
}
Printf(f_shadow, ":\n");
if (have_docstring(n)) {
@@ -2721,7 +2986,7 @@ public:
Delete(realct);
}
if (!have_constructor) {
- Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError, \"No constructor defined\"\n", NIL);
+ Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"No constructor defined\")\n", NIL);
} else if (fastinit) {
Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
@@ -2834,13 +3099,15 @@ public:
Delete(pycode);
fproxy = 0;
} else {
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, true, true, allow_kwargs);
if (!have_addtofunc(n)) {
if (!fastproxy || olddefs) {
- Printv(f_shadow, tab4, "def ", symname, "(*args", (allow_kwargs ? ", **kwargs" : ""), "):", NIL);
- Printv(f_shadow, " return ", funcCallHelper(Swig_name_member(class_name, symname), allow_kwargs), "\n", NIL);
+ Printv(f_shadow, tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":", NIL);
+ Printv(f_shadow, " return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
}
} else {
- Printv(f_shadow, tab4, "def ", symname, "(*args", (allow_kwargs ? ", **kwargs" : ""), "):", NIL);
+ Printv(f_shadow, tab4, "def ", symname, "(",parms , ")", returnTypeAnnotation(n), ":", NIL);
Printv(f_shadow, "\n", NIL);
if (have_docstring(n))
Printv(f_shadow, tab8, docstring(n, AUTODOC_METHOD, tab8), "\n", NIL);
@@ -2850,11 +3117,11 @@ public:
}
if (have_pythonappend(n)) {
fproxy = 0;
- Printv(f_shadow, tab8, "val = ", funcCallHelper(Swig_name_member(class_name, symname), allow_kwargs), "\n", NIL);
+ Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
Printv(f_shadow, tab8, pythonappend(n), "\n", NIL);
Printv(f_shadow, tab8, "return val\n\n", NIL);
} else {
- Printv(f_shadow, tab8, "return ", funcCallHelper(Swig_name_member(class_name, symname), allow_kwargs), "\n\n", NIL);
+ Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n\n", NIL);
}
}
}
@@ -2887,17 +3154,19 @@ public:
if (shadow) {
if (!classic && !Getattr(n, "feature:python:callback") && have_addtofunc(n)) {
int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
- Printv(f_shadow, tab4, "def ", symname, "(*args", (kw ? ", **kwargs" : ""), "):\n", NIL);
+ String *parms = make_pyParmList(n, true, false, kw);
+ String *callParms = make_pyParmList(n, true, true, kw);
+ Printv(f_shadow, tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_shadow, tab8, docstring(n, AUTODOC_STATICFUNC, tab8), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow, tab8, pythonprepend(n), "\n", NIL);
if (have_pythonappend(n)) {
- Printv(f_shadow, tab8, "val = ", funcCallHelper(Swig_name_member(class_name, symname), kw), "\n", NIL);
+ Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
Printv(f_shadow, tab8, pythonappend(n), "\n", NIL);
Printv(f_shadow, tab8, "return val\n\n", NIL);
} else {
- Printv(f_shadow, tab8, "return ", funcCallHelper(Swig_name_member(class_name, symname), kw), "\n\n", NIL);
+ Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n\n", NIL);
}
Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = staticmethod(", symname, ")\n", NIL);
@@ -2969,8 +3238,8 @@ public:
handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
Delete(cname);
}
-
- if (!have_constructor && handled_as_init) {
+
+ if (!have_constructor && handled_as_init) {
if (Getattr(n, "feature:shadow")) {
String *pycode = pythoncode(Getattr(n, "feature:shadow"), tab4);
String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(symname));
@@ -2984,23 +3253,30 @@ public:
String *classname = Swig_class_name(parent);
String *rclassname = Swig_class_name(getCurrentClass());
assert(rclassname);
- if (use_director) {
+
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ /* Pass 'self' only if using director */
+ String *callParms = make_pyParmList(n, false, true, allow_kwargs);
+
+ if (use_director) {
+ Insert(callParms, 0, "_self, ");
Printv(pass_self, tab8, NIL);
Printf(pass_self, "if self.__class__ == %s:\n", classname);
- Printv(pass_self, tab8, tab4, "args = (None,) + args\n", tab8, "else:\n", tab8, tab4, "args = (self,) + args\n", NIL);
+ //Printv(pass_self, tab8, tab4, "args = (None,) + args\n", tab8, "else:\n", tab8, tab4, "args = (self,) + args\n", NIL);
+ Printv(pass_self, tab8, tab4, "_self = None\n", tab8, "else:\n", tab8, tab4, "_self = self\n", NIL);
}
- Printv(f_shadow, tab4, "def __init__(self, *args", (allow_kwargs ? ", **kwargs" : ""), "): \n", NIL);
+ Printv(f_shadow, tab4, "def __init__(", parms, ")", returnTypeAnnotation(n), ": \n", NIL);
if (have_docstring(n))
Printv(f_shadow, tab8, docstring(n, AUTODOC_CTOR, tab8), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow, tab8, pythonprepend(n), "\n", NIL);
Printv(f_shadow, pass_self, NIL);
if (fastinit) {
- Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self,", funcCallHelper(Swig_name_construct(symname), allow_kwargs), ")\n", NIL);
+ Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self,", funcCall(Swig_name_construct(symname), callParms), ")\n", NIL);
} else {
Printv(f_shadow,
- tab8, "this = ", funcCallHelper(Swig_name_construct(symname), allow_kwargs), "\n",
+ tab8, "this = ", funcCall(Swig_name_construct(symname), callParms), "\n",
tab8, "try: self.this.append(this)\n", tab8, "except: self.this = this\n", NIL);
}
if (have_pythonappend(n))
@@ -3020,13 +3296,15 @@ public:
Printv(f_shadow_stubs, pycode, "\n", NIL);
Delete(pycode);
} else {
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, true, true, allow_kwargs);
- Printv(f_shadow_stubs, "\ndef ", symname, "(*args", (allow_kwargs ? ", **kwargs" : ""), "):\n", NIL);
+ Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow_stubs, tab4, pythonprepend(n), "\n", NIL);
- Printv(f_shadow_stubs, tab4, "val = ", funcCallHelper(Swig_name_construct(symname), allow_kwargs), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "val = ", funcCall(Swig_name_construct(symname), callParms), "\n", NIL);
#ifdef USE_THISOWN
Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL);
#endif
@@ -3605,15 +3883,15 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
if (use_parse || !modernargs) {
Printf(w->code, "swig::PyObject_var result = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n",
pyname, parse_args, arglist);
- } else {
- Printf(w->code, "swig::PyObject_var swig_method_name = PyString_FromString((char *)\"%s\");\n", pyname);
+ } else {
+ Printf(w->code, "swig::PyObject_var swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname);
Printf(w->code, "swig::PyObject_var result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name %s, NULL);\n", arglist);
}
} else {
if (!modernargs) {
Printf(w->code, "swig::PyObject_var result = PyObject_CallMethod(swig_get_self(), (char *) \"%s\", NULL);\n", pyname);
} else {
- Printf(w->code, "swig::PyObject_var swig_method_name = PyString_FromString((char *)\"%s\");\n", pyname);
+ Printf(w->code, "swig::PyObject_var swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname);
Append(w->code, "swig::PyObject_var result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n");
}
}
diff --git a/configure.in b/configure.in
index 77ff25aee..8a09cd6f7 100644
--- a/configure.in
+++ b/configure.in
@@ -573,7 +573,7 @@ else
# First figure out the name of the Python executable
if test "x$PYBIN" = xyes; then
-AC_CHECK_PROGS(PYTHON, python python2.8 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5 python1.4 python)
+AC_CHECK_PROGS(PYTHON, [python python2.8 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5 python1.4 python])
else
PYTHON="$PYBIN"
fi
@@ -657,6 +657,103 @@ AC_SUBST(PYLIB)
AC_SUBST(PYLINK)
AC_SUBST(PYTHONDYNAMICLINKING)
+
+#----------------------------------------------------------------
+# Look for Python 3.x
+#----------------------------------------------------------------
+
+# mostly copy & pasted from "Look for Python" section,
+# did some trim, fix and rename
+
+PY3INCLUDE=
+PY3LIB=
+PY3PACKAGE=
+
+AC_ARG_WITH(python3, AS_HELP_STRING([--without-python3], [Disable Python 3.x support])
+AS_HELP_STRING([--with-python3=path], [Set location of Python 3.x executable]),[ PY3BIN="$withval"], [PY3BIN=yes])
+
+# First, check for "--without-python3" or "--with-python3=no".
+if test x"${PY3BIN}" = xno -o x"${with_alllang}" = xno ; then
+AC_MSG_NOTICE([Disabling Python 3.x support])
+else
+# First figure out the name of the Python3 executable
+
+if test "x$PY3BIN" = xyes; then
+AC_CHECK_PROGS(PYTHON3, [python3 python3.0])
+else
+PYTHON3="$PY3BIN"
+fi
+
+# Check for Python 3.x development tools (header files, static library and python3-config)
+AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config python3-config python3.0-config])
+
+if test -n "$PYTHON3" -a -n "$PY3CONFIG"; then
+ AC_MSG_CHECKING([for Python 3.x prefix])
+ PY3PREFIX=`($PY3CONFIG --prefix) 2>/dev/null`
+ AC_MSG_RESULT($PY3PREFIX)
+ AC_MSG_CHECKING(for Python 3.x exec-prefix)
+ PY3EPREFIX=`($PY3CONFIG --exec-prefix) 2>/dev/null`
+ AC_MSG_RESULT($PY3EPREFIX)
+
+ # Note: I could not think of a standard way to get the version string from different versions.
+ # This trick pulls it out of the file location for a standard library file.
+
+ AC_MSG_CHECKING([for Python 3.x version])
+
+ # Need to do this hack since autoconf replaces __file__ with the name of the configure file
+ filehack="file__"
+ PY3VERSION=`($PYTHON3 -c "import string,operator,os.path; print(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))")`
+ AC_MSG_RESULT($PY3VERSION)
+
+ # Find the directory for libraries this is necessary to deal with
+ # platforms that can have apps built for multiple archs: e.g. x86_64
+ AC_MSG_CHECKING([for Python 3.x lib dir])
+ PY3LIBDIR=`($PYTHON3 -c "import sys; print(sys.lib)") 2>/dev/null`
+ if test -z "$PY3LIBDIR"; then
+ # some dists don't have sys.lib so the best we can do is assume lib
+ PY3LIBDIR="lib"
+ fi
+ AC_MSG_RESULT($PY3LIBDIR)
+
+ # Set the include directory
+
+ AC_MSG_CHECKING([for Python 3.x header files])
+ PY3INCLUDE=`($PY3CONFIG --includes) 2>/dev/null`
+ AC_MSG_RESULT($PY3INCLUDE)
+
+ # Set the library directory blindly. This probably won't work with older versions
+ AC_MSG_CHECKING([for Python 3.x library])
+ dirs="$PY3VERSION/config $PY3VERSION/$PY3LIBDIR python/$PY3LIBDIR"
+ for i in $dirs; do
+ if test -d $PY3EPREFIX/$PY3LIBDIR/$i; then
+ PY3LIB="$PY3EPREFIX/$PY3LIBDIR/$i"
+ break
+ fi
+ done
+ if test -z "$PY3LIB"; then
+ AC_MSG_RESULT([Not found])
+ else
+ AC_MSG_RESULT($PY3LIB)
+ fi
+
+ PY3LINK="-l$PY3VERSION"
+fi
+
+# Cygwin (Windows) needs the library for dynamic linking
+case $host in
+*-*-cygwin* | *-*-mingw*) PYTHON3DYNAMICLINKING="-L$PYLIB $PY3LINK"
+ DEFS="-DUSE_DL_IMPORT $DEFS" PY3INCLUDE="$PY3INCLUDE"
+ ;;
+*)PYTHON3DYNAMICLINKING="";;
+esac
+fi
+
+AC_SUBST(PY3INCLUDE)
+AC_SUBST(PY3LIB)
+AC_SUBST(PY3LINK)
+AC_SUBST(PYTHON3DYNAMICLINKING)
+
+
#----------------------------------------------------------------
# Look for Perl5
#----------------------------------------------------------------
@@ -1856,11 +1953,17 @@ AC_SUBST(SKIP_OCTAVE)
SKIP_PYTHON=
-if test -z "$PYINCLUDE" || test -z "$PYLIB" ; then
+if (test -z "$PYINCLUDE" || test -z "$PYLIB") &&
+ (test -z "$PY3INCLUDE" || test -z "PY3LIB") ; then
SKIP_PYTHON="1"
fi
AC_SUBST(SKIP_PYTHON)
+SKIP_PYTHON3=
+if test -z "$PY3INCLUDE" || test -z "$PY3LIB" ; then
+ SKIP_PYTHON3="1"
+fi
+AC_SUBST(SKIP_PYTHON3)
SKIP_JAVA=
if test -z "$JAVA" || test -z "$JAVAC" || test -z "$JAVAINC" ; then