Many, many (many!) changes needed to build and run the Phoenix extension modules with Python 3. Where possible changes were made such that the code works with both Python 2.7 and 3.2 without conditionals. In general the following types of changes were made:

* Changed imports to use either absolute or explicit relative imports.  Implicit relative imports are no longer allowed.

 * Changes to accomodate standard library classes or modues moving to other locations, or being removed entirely.

 * Changes related to print becoming a function, execfile being removed, u'' no longer allowed, and other syntax related issues.

 * Working around C APIs that have changed or simply vanished. (PyInt, PyString, PyBytes, etc.)

 * Dealing with text file objects using strings vs binary file objects using bytes, auto-encoding, and etc.

 * Replacing the use of PyCObject with PyCapsule and dealing with an apparent bug where PyCapsule objects can't be imported from submodules within a package.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@71554 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2012-05-24 23:28:02 +00:00
parent 7813eacd4b
commit b41df0b779
62 changed files with 521 additions and 365 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
*.pdb *.pdb
*.dll *.dll
.waf-* .waf-*
.waf3-*
.lock-waf* .lock-waf*

2
b
View File

@@ -4,6 +4,8 @@
PYVER=2.7 PYVER=2.7
PYVER2=27 PYVER2=27
#PYVER=3.2
#PYVER2=32
if [ "$OSTYPE" = "cygwin" ]; then if [ "$OSTYPE" = "cygwin" ]; then
$TOOLS/python$PYVER2/python.exe -u build.py "$@" $TOOLS/python$PYVER2/python.exe -u build.py "$@"

View File

@@ -5,6 +5,9 @@
# the Python extension mocdules. # the Python extension mocdules.
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
from __future__ import absolute_import
import sys
import glob import glob
import hashlib import hashlib
import optparse import optparse
@@ -16,13 +19,17 @@ import sys
import tarfile import tarfile
import tempfile import tempfile
import datetime import datetime
import urllib2 if sys.version_info < (3,):
from urllib2 import urlopen
else:
from urllib.request import urlopen
from distutils.dep_util import newer, newer_group from distutils.dep_util import newer, newer_group
from buildtools.config import Config, msg, opj, posixjoin, loadETG, etg2sip, findCmd, \ from buildtools.config import Config, msg, opj, posixjoin, loadETG, etg2sip, findCmd, \
phoenixDir, wxDir, copyIfNewer, copyFile, \ phoenixDir, wxDir, copyIfNewer, copyFile, \
macFixDependencyInstallName, macSetLoaderNames, \ macFixDependencyInstallName, macSetLoaderNames, \
getSvnRev, runcmd getSvnRev, runcmd, textfile_open
import buildtools.version as version import buildtools.version as version
@@ -226,17 +233,17 @@ def numCPUs():
""" """
# Linux, Unix and MacOS: # Linux, Unix and MacOS:
if hasattr(os, "sysconf"): if hasattr(os, "sysconf"):
if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): if "SC_NPROCESSORS_ONLN" in os.sysconf_names:
# Linux & Unix: # Linux & Unix:
ncpus = os.sysconf("SC_NPROCESSORS_ONLN") ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
if isinstance(ncpus, int) and ncpus > 0: if isinstance(ncpus, int) and ncpus > 0:
return ncpus return ncpus
else: # OSX: else: # OSX:
p = subprocess.Popen("sysctl -n hw.ncpu", shell=True, stdout=subprocess.PIPE) p = subprocess.Popen("sysctl -n hw.ncpu", shell=True, stdout=subprocess.PIPE)
return p.stdout.read() return int(p.stdout.read())
# Windows: # Windows:
if os.environ.has_key("NUMBER_OF_PROCESSORS"): if "NUMBER_OF_PROCESSORS" in os.environ:
ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]); ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]);
if ncpus > 0: if ncpus > 0:
return ncpus return ncpus
@@ -376,7 +383,7 @@ def getSipCmd():
msg('Not found. Attempting to download...') msg('Not found. Attempting to download...')
url = '%s/sip-%s-%s%s.bz2' % (toolsURL, sipCurrentVersion, platform, ext) url = '%s/sip-%s-%s%s.bz2' % (toolsURL, sipCurrentVersion, platform, ext)
try: try:
connection = urllib2.urlopen(url) connection = urlopen(url)
msg('Connection successful...') msg('Connection successful...')
data = connection.read() data = connection.read()
msg('Data downloaded...') msg('Data downloaded...')
@@ -391,7 +398,7 @@ def getSipCmd():
data = bz2.decompress(data) data = bz2.decompress(data)
with open(cmd, 'wb') as f: with open(cmd, 'wb') as f:
f.write(data) f.write(data)
os.chmod(cmd, 0755) os.chmod(cmd, 0o755)
return getSipCmd() return getSipCmd()
@@ -434,7 +441,7 @@ def getWafCmd():
msg('Not found. Attempting to download...') msg('Not found. Attempting to download...')
url = '%s/waf-%s' % (toolsURL, wafCurrentVersion) url = '%s/waf-%s' % (toolsURL, wafCurrentVersion)
try: try:
connection = urllib2.urlopen(url) connection = urlopen(url)
msg('Connection successful...') msg('Connection successful...')
data = connection.read() data = connection.read()
msg('Data downloaded...') msg('Data downloaded...')
@@ -562,7 +569,6 @@ def etg(options, args):
if newer_group(deps, sipfile): if newer_group(deps, sipfile):
runcmd('%s %s %s' % (PYTHON, script, flags)) runcmd('%s %s %s' % (PYTHON, script, flags))
def sphinx(options, args): def sphinx(options, args):
from sphinxtools.postprocess import SphinxIndexes, MakeHeadings, PostProcess, GenGallery from sphinxtools.postprocess import SphinxIndexes, MakeHeadings, PostProcess, GenGallery
@@ -714,7 +720,7 @@ def sip(options, args):
def processSrc(src, keepHashLines=False): def processSrc(src, keepHashLines=False):
with file(src, 'rt') as f: with textfile_open(src, 'rt') as f:
srcTxt = f.read() srcTxt = f.read()
if keepHashLines: if keepHashLines:
# Either just fix the pathnames in the #line lines... # Either just fix the pathnames in the #line lines...
@@ -733,20 +739,20 @@ def sip(options, args):
if not os.path.exists(dest): if not os.path.exists(dest):
msg('%s is a new file, copying...' % os.path.basename(src)) msg('%s is a new file, copying...' % os.path.basename(src))
srcTxt = processSrc(src, options.keep_hash_lines) srcTxt = processSrc(src, options.keep_hash_lines)
f = file(dest, 'wt') f = textfile_open(dest, 'wt')
f.write(srcTxt) f.write(srcTxt)
f.close() f.close()
continue continue
srcTxt = processSrc(src, options.keep_hash_lines) srcTxt = processSrc(src, options.keep_hash_lines)
with file(dest, 'rt') as f: with textfile_open(dest, 'rt') as f:
destTxt = f.read() destTxt = f.read()
if srcTxt == destTxt: if srcTxt == destTxt:
pass pass
else: else:
msg('%s is changed, copying...' % os.path.basename(src)) msg('%s is changed, copying...' % os.path.basename(src))
f = file(dest, 'wt') f = textfile_open(dest, 'wt')
f.write(srcTxt) f.write(srcTxt)
f.close() f.close()
@@ -1008,7 +1014,7 @@ def setup_py(options, args):
wxbuild.macFixupInstallNames(DESTDIR, PREFIX, BUILD_DIR) wxbuild.macFixupInstallNames(DESTDIR, PREFIX, BUILD_DIR)
# and also adjust the dependency names in the wxPython extensions # and also adjust the dependency names in the wxPython extensions
for line in file("installed_files.txt"): for line in open("installed_files.txt"):
line = line.strip() line = line.strip()
if line.endswith('.so'): if line.endswith('.so'):
macFixDependencyInstallName(DESTDIR, PREFIX, line, BUILD_DIR) macFixDependencyInstallName(DESTDIR, PREFIX, line, BUILD_DIR)
@@ -1043,6 +1049,8 @@ def waf_py(options, args):
build_options.append('--verbose') build_options.append('--verbose')
if options.jobs: if options.jobs:
build_options.append('--jobs=%s' % options.jobs) build_options.append('--jobs=%s' % options.jobs)
build_options.append('--python=%s' % PYTHON)
pwd = pushDir(phoenixDir()) pwd = pushDir(phoenixDir())
cmd = '%s %s %s configure build %s' % (PYTHON, waf, ' '.join(build_options), options.extra_waf) cmd = '%s %s %s configure build %s' % (PYTHON, waf, ' '.join(build_options), options.extra_waf)

View File

@@ -16,7 +16,6 @@ import os
import glob import glob
import fnmatch import fnmatch
import tempfile import tempfile
import commands
import shutil import shutil
import codecs import codecs
import subprocess import subprocess
@@ -26,8 +25,6 @@ from distutils.dir_util import mkpath
from distutils.dep_util import newer from distutils.dep_util import newer
from distutils.spawn import spawn from distutils.spawn import spawn
reload(sys)
sys.setdefaultencoding('utf-8')
runSilently = False runSilently = False
@@ -98,7 +95,8 @@ class Configuration(object):
self.CLEANUP = list() self.CLEANUP = list()
# load the version numbers into this instance's namespace # load the version numbers into this instance's namespace
execfile(opj(os.path.split(__file__)[0], 'version.py'), self.__dict__) versionfile = opj(os.path.split(__file__)[0], 'version.py')
myExecfile(versionfile, self.__dict__)
# If we're doing a dated build then alter the VERSION strings # If we're doing a dated build then alter the VERSION strings
if os.path.exists('DAILY_BUILD'): if os.path.exists('DAILY_BUILD'):
@@ -272,7 +270,7 @@ class Configuration(object):
self.WXPLAT = '__WXMSW__' self.WXPLAT = '__WXMSW__'
portcfg = '' portcfg = ''
else: else:
raise SystemExit, "Unknown WXPORT value: " + self.WXPORT raise SystemExit("Unknown WXPORT value: " + self.WXPORT)
self.cflags += portcfg.split() self.cflags += portcfg.split()
@@ -382,14 +380,18 @@ class Configuration(object):
def build_locale_list(self, srcdir): def build_locale_list(self, srcdir):
# get a list of all files under the srcdir, to be used for install_data # get a list of all files under the srcdir, to be used for install_data
def walk_helper(lst, dirname, files): if sys.version_info[0] == 2:
for f in files: def walk_helper(lst, dirname, files):
filename = opj(dirname, f) for f in files:
if not os.path.isdir(filename): filename = opj(dirname, f)
lst.append( (dirname, [filename]) ) if not os.path.isdir(filename):
file_list = [] lst.append( (dirname, [filename]) )
os.path.walk(srcdir, walk_helper, file_list) file_list = []
return file_list os.path.walk(srcdir, walk_helper, file_list)
return file_list
else:
# TODO: Python3 version using os.walk generator
return []
def find_data_files(self, srcdir, *wildcards, **kw): def find_data_files(self, srcdir, *wildcards, **kw):
@@ -558,7 +560,7 @@ def loadETG(name):
return self.__dict__ return self.__dict__
ns = _Namespace() ns = _Namespace()
execfile(name, ns.nsdict()) myExecfile(name, ns.nsdict())
return ns return ns
@@ -574,7 +576,7 @@ def _getSbfValue(etg, keyName):
cfg = Config() cfg = Config()
sbf = opj(cfg.SIPOUT, etg.NAME + '.sbf') sbf = opj(cfg.SIPOUT, etg.NAME + '.sbf')
out = list() out = list()
for line in file(sbf): for line in open(sbf):
key, value = line.split('=') key, value = line.split('=')
if key.strip() == keyName: if key.strip() == keyName:
return sorted([opj(cfg.SIPOUT, v) for v in value.strip().split()]) return sorted([opj(cfg.SIPOUT, v) for v in value.strip().split()])
@@ -750,6 +752,8 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True):
output = None output = None
if getOutput: if getOutput:
output = sp.stdout.read() output = sp.stdout.read()
if sys.version_info > (3,):
output = output.decode('utf-8') # TODO: is utf-8 okay here?
output = output.rstrip() output = output.rstrip()
rval = sp.wait() rval = sp.wait()
@@ -763,3 +767,22 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True):
return output return output
def myExecfile(filename, ns):
if sys.version_info < (3,):
execfile(filename, ns)
else:
source = open(filename, 'r').read()
exec(source, ns)
def textfile_open(filename, mode='rt'):
"""
Simple wrapper around open() that will open normally on Python 2.x and on
Python 2.3 will add the encoding parameter. The mode parameter must
include the 't' to put the stream into text mode.
"""
assert 't' in mode
if sys.version_info < (3,):
return open(filename, mode)
else:
return open(filename, mode, encoding='utf-8')

View File

@@ -17,9 +17,9 @@ import distutils.command.install
import distutils.command.install_data import distutils.command.install_data
import distutils.command.install_headers import distutils.command.install_headers
import distutils.command.clean import distutils.command.clean
from distutils.dep_util import newer, newer_group from distutils.dep_util import newer, newer_group
from config import Config, posixjoin, loadETG, etg2sip from .config import Config, posixjoin, loadETG, etg2sip
@@ -231,8 +231,8 @@ class MyUnixCCompiler(distutils.unixccompiler.UnixCCompiler):
try: try:
self.spawn(compiler_so + cc_args + [src, '-o', obj] + self.spawn(compiler_so + cc_args + [src, '-o', obj] +
extra_postargs) extra_postargs)
except DistutilsExecError, msg: except DistutilsExecError as msg:
raise CompileError, msg raise CompileError(msg)
_orig_parse_makefile = distutils.sysconfig.parse_makefile _orig_parse_makefile = distutils.sysconfig.parse_makefile
def _parse_makefile(filename, g=None): def _parse_makefile(filename, g=None):
@@ -289,14 +289,14 @@ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
#self.spawn(["windres", "-i", src, "-o", obj]) #self.spawn(["windres", "-i", src, "-o", obj])
self.spawn(["windres", "-i", src, "-o", obj] + self.spawn(["windres", "-i", src, "-o", obj] +
[arg for arg in cc_args if arg.startswith("-I")] ) [arg for arg in cc_args if arg.startswith("-I")] )
except DistutilsExecError, msg: except DistutilsExecError as msg:
raise CompileError, msg raise CompileError(msg)
else: # for other files use the C-compiler else: # for other files use the C-compiler
try: try:
self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
extra_postargs) extra_postargs)
except DistutilsExecError, msg: except DistutilsExecError as msg:
raise CompileError, msg raise CompileError(msg)
distutils.cygwinccompiler.CygwinCCompiler._compile = _compile distutils.cygwinccompiler.CygwinCCompiler._compile = _compile
@@ -327,7 +327,7 @@ if os.name == 'nt' and sys.version_info >= (2,6):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
from sipdistutils import build_ext from .sipdistutils import build_ext
class etgsip_build_ext(build_ext): class etgsip_build_ext(build_ext):
""" """

View File

@@ -84,7 +84,7 @@ def run():
module.addHeaderCode('#include <wxpy_api.h>') module.addHeaderCode('#include <wxpy_api.h>')
module.addImport('_core') module.addImport('_core')
module.addPyCode("import core as wx", order=10) module.addPyCode("import wx", order=10)
module.addInclude(INCLUDES) module.addInclude(INCLUDES)

View File

@@ -404,7 +404,7 @@ def run():
]) ])
module.addPreInitializerCode("""\ module.addInitializerCode("""\
wxPyPreInit(sipModuleDict); wxPyPreInit(sipModuleDict);
""") """)

View File

@@ -79,7 +79,7 @@ def run():
PyObject* o1 = PySequence_ITEM(obj, 0); PyObject* o1 = PySequence_ITEM(obj, 0);
PyObject* o2 = PySequence_ITEM(obj, 1); PyObject* o2 = PySequence_ITEM(obj, 1);
PyObject* o3 = PySequence_ITEM(obj, 2); PyObject* o3 = PySequence_ITEM(obj, 2);
tmpEntries[idx].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3)); tmpEntries[idx].Set(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3));
Py_DECREF(o1); Py_DECREF(o1);
Py_DECREF(o2); Py_DECREF(o2);
Py_DECREF(o3); Py_DECREF(o3);

View File

@@ -68,21 +68,21 @@ def run():
c.addCppMethod('PyObject*', 'GetPrivData', '()', """\ c.addCppMethod('PyObject*', 'GetPrivData', '()', """\
PyObject* data; PyObject* data;
wxPyBlock_t blocked = wxPyBeginBlockThreads(); wxPyBlock_t blocked = wxPyBeginBlockThreads();
data = PyString_FromStringAndSize(self->GetPrivData(), data = PyBytes_FromStringAndSize(self->GetPrivData(),
self->GetPrivDataLen()); self->GetPrivDataLen());
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);
return data; return data;
""") """)
c.addCppMethod('void', 'SetPrivData', '(PyObject* data)', """\ c.addCppMethod('void', 'SetPrivData', '(PyObject* data)', """\
if (! PyString_Check(data)) { if (! PyBytes_Check(data)) {
wxPyBLOCK_THREADS(PyErr_SetString(PyExc_TypeError, wxPyBLOCK_THREADS(PyErr_SetString(PyExc_TypeError,
"Expected string object")); "Expected string object"));
return /* NULL */ ; return /* NULL */ ;
} }
wxPyBlock_t blocked = wxPyBeginBlockThreads(); wxPyBlock_t blocked = wxPyBeginBlockThreads();
self->SetPrivData(PyString_AS_STRING(data), PyString_GET_SIZE(data)); self->SetPrivData(PyBytes_AS_STRING(data), PyBytes_GET_SIZE(data));
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);
""") """)

View File

@@ -185,7 +185,7 @@ def run():
return 1; return 1;
if (sipCanConvertToType(sipPy, sipType_wxColour, SIP_NO_CONVERTORS)) if (sipCanConvertToType(sipPy, sipType_wxColour, SIP_NO_CONVERTORS))
return 1; return 1;
if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
return 1; return 1;
if (PySequence_Check(sipPy)) { if (PySequence_Check(sipPy)) {
size_t len = PySequence_Size(sipPy); size_t len = PySequence_Size(sipPy);
@@ -210,7 +210,7 @@ def run():
return sipGetState(sipTransferObj); return sipGetState(sipTransferObj);
} }
// Is it a string? // Is it a string?
else if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) { else if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) {
wxString spec = Py2wxString(sipPy); wxString spec = Py2wxString(sipPy);
if (spec.GetChar(0) == '#' if (spec.GetChar(0) == '#'
&& (spec.length() == 7 || spec.length() == 9)) { // It's #RRGGBB[AA] && (spec.length() == 7 || spec.length() == 9)) { // It's #RRGGBB[AA]
@@ -251,11 +251,11 @@ def run():
PyObject* o2 = PySequence_GetItem(sipPy, 1); PyObject* o2 = PySequence_GetItem(sipPy, 1);
PyObject* o3 = PySequence_GetItem(sipPy, 2); PyObject* o3 = PySequence_GetItem(sipPy, 2);
if (len == 3) if (len == 3)
*sipCppPtr = new wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3)); *sipCppPtr = new wxColour(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3));
else { else {
PyObject* o4 = PySequence_GetItem(sipPy, 3); PyObject* o4 = PySequence_GetItem(sipPy, 3);
*sipCppPtr = new wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3), *sipCppPtr = new wxColour(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3),
PyInt_AsLong(o4)); wxPyInt_AsLong(o4));
Py_DECREF(o4); Py_DECREF(o4);
} }
Py_DECREF(o1); Py_DECREF(o1);

View File

@@ -165,7 +165,7 @@ def run():
if (!fmtObj) goto error; if (!fmtObj) goto error;
sizeObj = PyObject_CallMethod(self, "GetDataSize", "(O)", fmtObj, NULL); sizeObj = PyObject_CallMethod(self, "GetDataSize", "(O)", fmtObj, NULL);
if (!sizeObj) goto error; if (!sizeObj) goto error;
size = PyInt_AsSsize_t(sizeObj); size = wxPyInt_AsSsize_t(sizeObj);
// Make a buffer that big using the pointer passed to us, and then // Make a buffer that big using the pointer passed to us, and then
// call the Python method. // call the Python method.
@@ -237,7 +237,7 @@ def run():
sizeObj = PyObject_CallMethod(self, "GetDataSize", "", NULL); sizeObj = PyObject_CallMethod(self, "GetDataSize", "", NULL);
if (!sizeObj) goto error; if (!sizeObj) goto error;
size = PyInt_AsSsize_t(sizeObj); size = wxPyInt_AsSsize_t(sizeObj);
// Make a buffer that big using the pointer passed to us, and then // Make a buffer that big using the pointer passed to us, and then
// call the Python method. // call the Python method.

View File

@@ -106,7 +106,7 @@ def run():
PyFunctionDef('__init__', '(self, evtType, expectedIDs=0)', PyFunctionDef('__init__', '(self, evtType, expectedIDs=0)',
body="""\ body="""\
if expectedIDs not in [0, 1, 2]: if expectedIDs not in [0, 1, 2]:
raise ValueError, "Invalid number of expectedIDs" raise ValueError("Invalid number of expectedIDs")
self.expectedIDs = expectedIDs self.expectedIDs = expectedIDs
if isinstance(evtType, (list, tuple)): if isinstance(evtType, (list, tuple)):
@@ -205,10 +205,11 @@ def run():
(entry->m_callbackUserData != NULL)) (entry->m_callbackUserData != NULL))
{ {
wxPyCallback *cb = (wxPyCallback*)entry->m_callbackUserData; wxPyCallback *cb = (wxPyCallback*)entry->m_callbackUserData;
wxPyBlock_t blocked = wxPyBeginBlockThreads(); //wxPyBlock_t blocked = wxPyBeginBlockThreads();
int result = PyObject_Compare(cb->m_func, func); //int result = PyObject_Compare(cb->m_func, func);
wxPyEndBlockThreads(blocked); //wxPyEndBlockThreads(blocked);
if (result == 0) { //if (result == 0) {
if (cb->m_func == func) {
delete cb; delete cb;
self->GetDynamicEventTable()->Erase(node); self->GetDynamicEventTable()->Erase(node);
delete entry; delete entry;

View File

@@ -73,7 +73,7 @@ def run():
PyObject* result = PyEval_CallObject(func, args); PyObject* result = PyEval_CallObject(func, args);
Py_DECREF(args); Py_DECREF(args);
if (result) { if (result) {
retval = PyInt_AsLong(result); retval = wxPyInt_AsLong(result);
Py_DECREF(result); Py_DECREF(result);
} }

View File

@@ -78,6 +78,7 @@ def run():
if self._iterator.HaveRects(): if self._iterator.HaveRects():
self._iterator.Next() self._iterator.Next()
return rect return rect
__next__ = next # for Python 3
""") """)

View File

@@ -118,7 +118,7 @@ def run():
} }
else { else {
// Return the data as a string object. TODO: Py3 // Return the data as a string object. TODO: Py3
obj = PyString_FromStringAndSize(buf, buf.GetDataLen()); obj = PyBytes_FromStringAndSize(buf, buf.GetDataLen());
} }
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);
return obj; return obj;
@@ -205,7 +205,7 @@ def run():
} }
wxPyBlock_t blocked = wxPyBeginBlockThreads(); wxPyBlock_t blocked = wxPyBeginBlockThreads();
PyList_Append(pylist, s); PyList_Append(pylist, s);
i += PyString_Size(s); i += PyBytes_Size(s);
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);
} }
@@ -274,12 +274,12 @@ def run():
c.addCppMethod('void', 'write', '(PyObject* data)', """\ c.addCppMethod('void', 'write', '(PyObject* data)', """\
// We use only strings for the streams, not unicode // We use only strings for the streams, not unicode
PyObject* str = PyObject_Str(data); PyObject* str = PyObject_Bytes(data);
if (! str) { if (! str) {
PyErr_SetString(PyExc_TypeError, "Unable to convert to string"); PyErr_SetString(PyExc_TypeError, "Unable to convert to string");
return; return;
} }
self->Write(PyString_AS_STRING(str), PyString_GET_SIZE(str)); self->Write(PyBytes_AS_STRING(str), PyBytes_GET_SIZE(str));
Py_DECREF(str); Py_DECREF(str);
""") """)

View File

@@ -169,6 +169,8 @@ def run():
import wx.siplib import wx.siplib
return not wx.siplib.isdeleted(self) return not wx.siplib.isdeleted(self)
""") """)
c.addPyCode('Window.__bool__ = Window.__nonzero__') # For Python 3
# MSW only. Do we want them wrapped? # MSW only. Do we want them wrapped?
c.find('GetAccessible').ignore() c.find('GetAccessible').ignore()

View File

@@ -13,7 +13,7 @@ them from the Doxygen XML, and producing wrapper code from them.
""" """
import sys, os import sys, os
from extractors import * from .extractors import *
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -68,7 +68,7 @@ def parseDoxyXML(module, class_or_filename_list):
if not os.path.exists(pathname): if not os.path.exists(pathname):
pathname = os.path.join(XMLSRC, class_or_filename) pathname = os.path.join(XMLSRC, class_or_filename)
if verbose(): if verbose():
print "Loading %s..." % pathname print("Loading %s..." % pathname)
_filesparsed.add(pathname) _filesparsed.add(pathname)
root = et.parse(pathname).getroot() root = et.parse(pathname).getroot()

View File

@@ -17,8 +17,9 @@ import os
import pprint import pprint
import xml.etree.ElementTree as et import xml.etree.ElementTree as et
from tweaker_tools import removeWxPrefix, magicMethods, \ from .tweaker_tools import removeWxPrefix, magicMethods, \
guessTypeInt, guessTypeFloat, guessTypeStr guessTypeInt, guessTypeFloat, guessTypeStr, \
textfile_open
from sphinxtools.utilities import FindDescendants from sphinxtools.utilities import FindDescendants
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -571,7 +572,7 @@ class ParamDef(BaseDef):
if element.find('defval') is not None: if element.find('defval') is not None:
self.default = flattenNode(element.find('defval')) self.default = flattenNode(element.find('defval'))
except: except:
print "error when parsing element:" print("error when parsing element:")
et.dump(element) et.dump(element)
raise raise
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -725,7 +726,7 @@ class ClassDef(BaseDef):
def includeCppCode(self, filename): def includeCppCode(self, filename):
self.addCppCode(file(filename).read()) self.addCppCode(textfile_open(filename).read())
def addAutoProperties(self): def addAutoProperties(self):
@@ -823,9 +824,9 @@ class ClassDef(BaseDef):
# only create the prop if a method with that name does not exist, and it is a valid name # only create the prop if a method with that name does not exist, and it is a valid name
if starts_with_number: if starts_with_number:
print 'WARNING: Invalid property name %s for class %s' % (name, self.name) print('WARNING: Invalid property name %s for class %s' % (name, self.name))
elif self.findItem(name): elif self.findItem(name):
print "WARNING: Method %s::%s already exists in C++ class API, can not create a property." % (self.name, name) print("WARNING: Method %s::%s already exists in C++ class API, can not create a property." % (self.name, name))
else: else:
self.items.append(prop) self.items.append(prop)
@@ -1307,7 +1308,7 @@ class ModuleDef(BaseDef):
self.cppCode.append(code) self.cppCode.append(code)
def includeCppCode(self, filename): def includeCppCode(self, filename):
self.addCppCode(file(filename).read()) self.addCppCode(textfile_open(filename).read())
def addInitializerCode(self, code): def addInitializerCode(self, code):
if isinstance(code, list): if isinstance(code, list):
@@ -1447,7 +1448,7 @@ class ModuleDef(BaseDef):
""" """
Add a snippet of Python code from a file to the wrapper module. Add a snippet of Python code from a file to the wrapper module.
""" """
text = file(filename).read() text = textfile_open(filename).read()
return self.addPyCode( return self.addPyCode(
"#" + '-=' * 38 + '\n' + "#" + '-=' * 38 + '\n' +
("# This code block was included from %s\n%s\n" % (filename, text)) + ("# This code block was included from %s\n%s\n" % (filename, text)) +
@@ -1487,7 +1488,11 @@ def flattenNode(node, rstrip=True):
""" """
if node is None: if node is None:
return "" return ""
if isinstance(node, basestring): if sys.version_info < (3,):
strclass = basestring
else:
strclass = str
if isinstance(node, strclass):
return node return node
text = node.text or "" text = node.text or ""
for n in node: for n in node:
@@ -1526,11 +1531,11 @@ def verbose():
def extractingMsg(kind, element, nameTag='name'): def extractingMsg(kind, element, nameTag='name'):
if verbose(): if verbose():
print 'Extracting %s: %s' % (kind, element.find(nameTag).text) print('Extracting %s: %s' % (kind, element.find(nameTag).text))
def skippingMsg(kind, element): def skippingMsg(kind, element):
if verbose(): if verbose():
print 'Skipping %s: %s' % (kind, element.find('name').text) print('Skipping %s: %s' % (kind, element.find('name').text))
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -11,6 +11,7 @@
Just some base classes and stubs for the various generators Just some base classes and stubs for the various generators
""" """
import sys
class WrapperGeneratorBase(object): class WrapperGeneratorBase(object):
def __init__(self): def __init__(self):
@@ -79,12 +80,37 @@ def nci(text, numSpaces=0, stripLeading=True):
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
from StringIO import StringIO if sys.version_info < (3,):
# For Python 2.x we'll convert any unicode text values to strings before
# adding them to the buffer
from StringIO import StringIO
class Utf8EncodingStream(StringIO):
def write(self, text):
if isinstance(text, unicode):
text = text.encode('utf-8')
return StringIO.write(self, text)
class Utf8EncodingStream(StringIO): else:
def write(self, text): # For Python 3.x we'll keep it all as str (unicode) objects and let the
if isinstance(text, unicode): # conversion to bytes happen when the text is written to the actual
text = text.encode('utf-8') # file.
return StringIO.write(self, text) #super(EncodingStream, self).write(text) from io import StringIO
class Utf8EncodingStream(StringIO):
pass
def textfile_open(filename, mode='rt'):
"""
Simple wrapper around open() that will open normally on Python 2.x and on
Python 2.3 will add the encoding parameter. The mode parameter must
include the 't' to put the stream into text mode.
"""
assert 't' in mode
if sys.version_info < (3,):
return open(filename, mode)
else:
return open(filename, mode, encoding='utf-8')
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -17,11 +17,11 @@ completion, displaying docstrings in the source assistant panel, etc.
""" """
import sys, os, re import sys, os, re
import extractors import etgtools.extractors as extractors
import generators import etgtools.generators as generators
from generators import nci, Utf8EncodingStream from etgtools.generators import nci, Utf8EncodingStream, textfile_open
from tweaker_tools import removeWxPrefix, magicMethods, \ from etgtools.tweaker_tools import removeWxPrefix, magicMethods, \
guessTypeInt, guessTypeFloat, guessTypeStr guessTypeInt, guessTypeFloat, guessTypeStr
phoenixRoot = os.path.abspath(os.path.split(__file__)[0]+'/..') phoenixRoot = os.path.abspath(os.path.split(__file__)[0]+'/..')
@@ -57,7 +57,7 @@ class PiWrapperGenerator(generators.WrapperGeneratorBase):
if not os.path.exists(destFile): if not os.path.exists(destFile):
# create the file and write the header # create the file and write the header
f = file(destFile, 'wt') f = textfile_open(destFile, 'wt')
f.write(header) f.write(header)
f.close() f.close()
@@ -75,7 +75,7 @@ class PiWrapperGenerator(generators.WrapperGeneratorBase):
sectionBeginMarker = '#-- begin-%s --#' % sectionName sectionBeginMarker = '#-- begin-%s --#' % sectionName
sectionEndMarker = '#-- end-%s --#' % sectionName sectionEndMarker = '#-- end-%s --#' % sectionName
lines = file(destFile, 'rt').readlines() lines = textfile_open(destFile, 'rt').readlines()
for idx, line in enumerate(lines): for idx, line in enumerate(lines):
if line.startswith(sectionBeginMarker): if line.startswith(sectionBeginMarker):
sectionBeginLine = idx sectionBeginLine = idx
@@ -91,9 +91,8 @@ class PiWrapperGenerator(generators.WrapperGeneratorBase):
# replace the existing lines # replace the existing lines
lines[sectionBeginLine+1:sectionEndLine] = [sectionText] lines[sectionBeginLine+1:sectionEndLine] = [sectionText]
f = file(destFile, 'wt') f = textfile_open(destFile, 'wt')
f.writelines(lines) f.writelines(lines)
#f.write('\n')
f.close() f.close()

View File

@@ -13,9 +13,9 @@ objects produced by the ETG scripts.
""" """
import sys, os, re import sys, os, re
import extractors import etgtools.extractors as extractors
import generators import etgtools.generators as generators
from generators import nci, Utf8EncodingStream from etgtools.generators import nci, Utf8EncodingStream, textfile_open
divider = '//' + '-'*75 + '\n' divider = '//' + '-'*75 + '\n'
@@ -45,7 +45,7 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
# Write the contents of the stream to the destination file # Write the contents of the stream to the destination file
if not destFile: if not destFile:
destFile = os.path.join(phoenixRoot, 'sip/gen', module.name + '.sip') destFile = os.path.join(phoenixRoot, 'sip/gen', module.name + '.sip')
file(destFile, 'wt').write(stream.getvalue()) textfile_open(destFile, 'wt').write(stream.getvalue())
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
@@ -90,7 +90,7 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
# Copyright: (c) 2011 by Total Control Software # Copyright: (c) 2011 by Total Control Software
# License: wxWindows License # License: wxWindows License
%s %s
from %s import * from .%s import *
%%End %%End

View File

@@ -28,8 +28,8 @@ from StringIO import StringIO
import xml.etree.ElementTree as et import xml.etree.ElementTree as et
# Phoenix-specific stuff # Phoenix-specific stuff
import extractors import etgtools.extractors as extractors
import generators import etgtools.generators as generators
# Sphinx-Phoenix specific stuff # Sphinx-Phoenix specific stuff
from sphinxtools.inheritance import InheritanceDiagram from sphinxtools.inheritance import InheritanceDiagram

View File

@@ -12,7 +12,8 @@ Some helpers and utility functions that can assist with the tweaker
stage of the ETG scripts. stage of the ETG scripts.
""" """
import extractors import etgtools as extractors
from .generators import textfile_open
import sys, os import sys, os
import copy import copy
@@ -32,6 +33,7 @@ magicMethods = {
# TODO: add more # TODO: add more
} }
def removeWxPrefixes(node): def removeWxPrefixes(node):
""" """
Rename items with a 'wx' prefix to not have the prefix. If the back-end Rename items with a 'wx' prefix to not have the prefix. If the back-end
@@ -374,28 +376,28 @@ def getWrapperGenerator():
A simple factory function to create a wrapper generator class of the desired type. A simple factory function to create a wrapper generator class of the desired type.
""" """
if '--swig' in sys.argv: if '--swig' in sys.argv:
import swig_generator from etgtools import swig_generator
gClass = swig_generator.SwigWrapperGenerator gClass = swig_generator.SwigWrapperGenerator
elif '--sip' in sys.argv: elif '--sip' in sys.argv:
import sip_generator from etgtools import sip_generator
gClass = sip_generator.SipWrapperGenerator gClass = sip_generator.SipWrapperGenerator
else: else:
# The default is sip # The default is sip
import sip_generator from etgtools import sip_generator
gClass = sip_generator.SipWrapperGenerator gClass = sip_generator.SipWrapperGenerator
return gClass() return gClass()
def getDocsGenerator(): def getDocsGenerator():
if '--nodoc' in sys.argv: if '--nodoc' in sys.argv:
import generators from etgtools import generators
return generators.StubbedDocsGenerator() return generators.StubbedDocsGenerator()
elif '--sphinx' in sys.argv: elif '--sphinx' in sys.argv:
import sphinx_generator from etgtools import sphinx_generator
return sphinx_generator.SphinxGenerator() return sphinx_generator.SphinxGenerator()
else: else:
# the current default is sphinx # the current default is sphinx
import sphinx_generator from etgtools import sphinx_generator
return sphinx_generator.SphinxGenerator() return sphinx_generator.SphinxGenerator()
@@ -409,7 +411,7 @@ def runGenerators(module):
generators.append(getWrapperGenerator()) generators.append(getWrapperGenerator())
# Toss in the PI generator too # Toss in the PI generator too
import pi_generator from etgtools import pi_generator
generators.append(pi_generator.PiWrapperGenerator()) generators.append(pi_generator.PiWrapperGenerator())
# And finally add the documentation generator # And finally add the documentation generator
@@ -425,7 +427,7 @@ def checkForUnitTestModule(module):
pathname = 'unittests/test_%s.py' % module.name pathname = 'unittests/test_%s.py' % module.name
if os.path.exists(pathname) or not module.check4unittest: if os.path.exists(pathname) or not module.check4unittest:
return return
print 'WARNING: Unittest module (%s) not found!' % pathname print('WARNING: Unittest module (%s) not found!' % pathname)
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -464,7 +466,7 @@ def convertTwoIntegersTemplate(CLASS):
// or create a new instance // or create a new instance
PyObject* o1 = PySequence_ITEM(sipPy, 0); PyObject* o1 = PySequence_ITEM(sipPy, 0);
PyObject* o2 = PySequence_ITEM(sipPy, 1); PyObject* o2 = PySequence_ITEM(sipPy, 1);
*sipCppPtr = new {CLASS}(PyInt_AsLong(o1), PyInt_AsLong(o2)); *sipCppPtr = new {CLASS}(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2));
Py_DECREF(o1); Py_DECREF(o1);
Py_DECREF(o2); Py_DECREF(o2);
return SIP_TEMPORARY; return SIP_TEMPORARY;
@@ -509,8 +511,8 @@ def convertFourIntegersTemplate(CLASS):
PyObject* o2 = PySequence_ITEM(sipPy, 1); PyObject* o2 = PySequence_ITEM(sipPy, 1);
PyObject* o3 = PySequence_ITEM(sipPy, 2); PyObject* o3 = PySequence_ITEM(sipPy, 2);
PyObject* o4 = PySequence_ITEM(sipPy, 3); PyObject* o4 = PySequence_ITEM(sipPy, 3);
*sipCppPtr = new {CLASS}(PyInt_AsLong(o1), PyInt_AsLong(o2), *sipCppPtr = new {CLASS}(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2),
PyInt_AsLong(o3), PyInt_AsLong(o4)); wxPyInt_AsLong(o3), wxPyInt_AsLong(o4));
Py_DECREF(o1); Py_DECREF(o1);
Py_DECREF(o2); Py_DECREF(o2);
return SIP_TEMPORARY; return SIP_TEMPORARY;
@@ -724,7 +726,7 @@ del _{ListClass_pyName}___repr__
if (! PySequence_Check(sipPy)) if (! PySequence_Check(sipPy))
success = FALSE; success = FALSE;
// ensure it is not a string or unicode object (they are sequences too) // ensure it is not a string or unicode object (they are sequences too)
else if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) else if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
success = FALSE; success = FALSE;
// ensure each item can be converted to {ItemClass} // ensure each item can be converted to {ItemClass}
else {{ else {{
@@ -871,7 +873,7 @@ static
if (! PySequence_Check(source)) if (! PySequence_Check(source))
goto error0; goto error0;
// ensure it is not a string or unicode object (they are sequences too) // ensure it is not a string or unicode object (they are sequences too)
else if (PyString_Check(source) || PyUnicode_Check(source)) else if (PyBytes_Check(source) || PyUnicode_Check(source))
goto error0; goto error0;
// ensure each item can be converted to {objType} // ensure each item can be converted to {objType}
else {{ else {{

View File

@@ -1,15 +1,22 @@
import wx import sys, os, wx
print wx.version() print(wx.version()); print(sys.version)
#import os; print 'PID:', os.getpid(); raw_input('Ready to start, press enter...')
app = wx.App() app = wx.App()
frm = wx.Frame(None, title="Hello World!") frm = wx.Frame(None, title="Hello World!")
pnl = wx.Panel(frm) pnl = wx.Panel(frm)
pnl.BackgroundColour = 'sky blue' pnl.BackgroundColour = 'sky blue'
st = wx.StaticText(pnl, -1, 'This is wxPython\n%s' % wx.version(), (15,15))
st = wx.StaticText(pnl, -1, 'Hello World!', (15,10))
st.SetFont(wx.Font(14, wx.FONTFAMILY_SWISS, wx.FONTFLAG_BOLD)) st.SetFont(wx.Font(14, wx.FONTFAMILY_SWISS, wx.FONTFLAG_BOLD))
st = wx.StaticText(pnl, pos=(15,40), label=
'This is wxPython %s\nrunning on Python %s' %
(wx.version(), sys.version.split(' ')[0]))
st.SetFont(wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTFLAG_BOLD))
bmp = wx.Bitmap(os.path.join(os.path.dirname(__file__), 'phoenix_main.png'))
sb = wx.StaticBitmap(pnl, label=bmp, pos=(15,85))
frm.Show() frm.Show()
app.MainLoop() app.MainLoop()

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -184,7 +184,7 @@ class Enumeration(object):
def __getattr__(self, attr): def __getattr__(self, attr):
if not self.lookup.has_key(attr): if not attr in self.lookup:
raise AttributeError raise AttributeError
return self.lookup[attr] return self.lookup[attr]

View File

@@ -11,20 +11,24 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Standard library imports # Standard library imports
import sys
import os import os
import codecs import codecs
import shutil import shutil
import cPickle if sys.version_info < (3,):
import cPickle as pickle
from UserDict import UserDict from UserDict import UserDict
else:
import pickle
from collections import UserDict
# Phoenix-specific imports # Phoenix-specific imports
from templates import TEMPLATE_CONTRIB from .templates import TEMPLATE_CONTRIB
from constants import IGNORE, PUNCTUATION from .constants import IGNORE, PUNCTUATION
from constants import CPP_ITEMS, VERSION, VALUE_MAP from .constants import CPP_ITEMS, VERSION, VALUE_MAP
from constants import RE_KEEP_SPACES, EXTERN_INHERITANCE from .constants import RE_KEEP_SPACES, EXTERN_INHERITANCE
from constants import DOXYROOT, SPHINXROOT, WIDGETS_IMAGES_ROOT from .constants import DOXYROOT, SPHINXROOT, WIDGETS_IMAGES_ROOT
# ----------------------------------------------------------------------- # # ----------------------------------------------------------------------- #
@@ -577,14 +581,14 @@ def PickleItem(description, current_module, name, kind):
if os.path.isfile(pickle_file): if os.path.isfile(pickle_file):
fid = open(pickle_file, 'rb') fid = open(pickle_file, 'rb')
items = cPickle.load(fid) items = pickle.load(fid)
fid.close() fid.close()
else: else:
items = {} items = {}
items[name] = description items[name] = description
fid = open(pickle_file, 'wb') fid = open(pickle_file, 'wb')
cPickle.dump(items, fid) pickle.dump(items, fid)
fid.close() fid.close()
@@ -592,7 +596,7 @@ def PickleItem(description, current_module, name, kind):
def PickleClassInfo(class_name, element, short_description): def PickleClassInfo(class_name, element, short_description):
""" """
Saves some information about a class in a cPickle-compatible file., i.e. the Saves some information about a class in a pickle-compatible file., i.e. the
list of methods in that class and its super-classes. list of methods in that class and its super-classes.
:param string `class_name`: the name of the class we want to pickle; :param string `class_name`: the name of the class we want to pickle;
@@ -604,7 +608,7 @@ def PickleClassInfo(class_name, element, short_description):
if os.path.isfile(pickle_file): if os.path.isfile(pickle_file):
fid = open(pickle_file, 'rb') fid = open(pickle_file, 'rb')
items = cPickle.load(fid) items = pickle.load(fid)
fid.close() fid.close()
else: else:
items = {} items = {}
@@ -618,7 +622,7 @@ def PickleClassInfo(class_name, element, short_description):
items[class_name] = (method_list, bases, short_description) items[class_name] = (method_list, bases, short_description)
fid = open(pickle_file, 'wb') fid = open(pickle_file, 'wb')
cPickle.dump(items, fid) pickle.dump(items, fid)
fid.close() fid.close()

View File

@@ -8,11 +8,11 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Load the main version string into the package namespace # Load the main version string into the package namespace
import __version__ import wx.__version__
__version__ = __version__.VERSION_STRING __version__ = wx.__version__.VERSION_STRING
# Import all items from the core wxPython modules so they appear in the wx # Import all items from the core wxPython modules so they appear in the wx
# package namespace. # package namespace.
from core import * from wx.core import *

View File

@@ -194,20 +194,31 @@ void wxPyApp::_BootstrapApp()
// Copy the values in Python's sys.argv list to a C array of char* to // Copy the values in Python's sys.argv list to a C array of char* to
// be passed to the wxEntryStart function below. // be passed to the wxEntryStart function below.
int argc = 0; #if PY_MAJOR_VERSION >= 3
char** argv = NULL; #define argType wchar_t
#else
#define argType char
#endif
int argc = 0;
argType** argv = NULL;
blocked = wxPyBeginBlockThreads(); blocked = wxPyBeginBlockThreads();
PyObject* sysargv = PySys_GetObject("argv"); PyObject* sysargv = PySys_GetObject("argv");
if (sysargv != NULL) { if (sysargv != NULL) {
argc = PyList_Size(sysargv); argc = PyList_Size(sysargv);
argv = new char*[argc+1]; argv = new argType*[argc+1];
int x; int x;
for(x=0; x<argc; x++) { for(x=0; x<argc; x++) {
PyObject *pyArg = PyList_GetItem(sysargv, x); // borrowed reference PyObject *pyArg = PyList_GetItem(sysargv, x); // borrowed reference
// if there isn't anything in sys.argv[0] then set it to the python executable // if there isn't anything in sys.argv[0] then set it to the python executable
if (x == 0 && PyObject_Length(pyArg) < 1) if (x == 0 && PyObject_Length(pyArg) < 1)
pyArg = PySys_GetObject("executable"); pyArg = PySys_GetObject("executable");
argv[x] = strdup(PyString_AsString(pyArg)); #if PY_MAJOR_VERSION >= 3
int len = PyObject_Length(pyArg);
argv[x] = new argType[len+1];
wxPyUnicode_AsWideChar(pyArg, argv[x], len+1);
#else
argv[x] = strdup(PyBytes_AsString(pyArg));
#endif
} }
argv[argc] = NULL; argv[argc] = NULL;
} }

View File

@@ -25,14 +25,14 @@
if (! PySequence_Check(sipPy)) if (! PySequence_Check(sipPy))
success = FALSE; success = FALSE;
// Ensure it is not a string or unicode object (they are sequences) // Ensure it is not a string or unicode object (they are sequences)
else if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) else if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
success = FALSE; success = FALSE;
// ensure each item is a string/unicode object // ensure each item is a string/unicode object
else { else {
Py_ssize_t i, len = PySequence_Length(sipPy); Py_ssize_t i, len = PySequence_Length(sipPy);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i); PyObject* item = PySequence_GetItem(sipPy, i);
if (!PyString_Check(item) && !PyUnicode_Check(item)) { if (!PyBytes_Check(item) && !PyUnicode_Check(item)) {
Py_DECREF(item); Py_DECREF(item);
success = FALSE; success = FALSE;
break; break;
@@ -52,7 +52,7 @@
PyObject* item = PySequence_GetItem(sipPy, i); PyObject* item = PySequence_GetItem(sipPy, i);
// if it's a string object convert it to unicode first, assuming utf-8 // if it's a string object convert it to unicode first, assuming utf-8
if (PyString_Check(item)) { if (PyBytes_Check(item)) {
Py_DECREF(item); Py_DECREF(item);
item = PyUnicode_FromEncodedObject(item, "utf-8", "strict"); item = PyUnicode_FromEncodedObject(item, "utf-8", "strict");
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
@@ -65,8 +65,7 @@
wxString string; wxString string;
size_t len = PyUnicode_GET_SIZE(item); size_t len = PyUnicode_GET_SIZE(item);
if (len) { if (len) {
PyUnicode_AsWideChar((PyUnicodeObject*)item, wxPyUnicode_AsWideChar(item, wxStringBuffer(string, len), len);
wxStringBuffer(string, len), len);
} }
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
*sipIsErr = 1; *sipIsErr = 1;
@@ -141,14 +140,14 @@ wxArrayString testArrayStringTypemap(const wxArrayString& arr);
Py_ssize_t i, len = PySequence_Length(sipPy); Py_ssize_t i, len = PySequence_Length(sipPy);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i); PyObject* item = PySequence_GetItem(sipPy, i);
PyObject* number = PyNumber_Int(item); PyObject* number = wxPyNumber_Int(item);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
*sipIsErr = 1; *sipIsErr = 1;
delete array; delete array;
Py_DECREF(item); Py_DECREF(item);
return 0; return 0;
} }
array->Add(PyInt_AS_LONG(number)); array->Add(wxPyInt_AS_LONG(number));
Py_DECREF(item); Py_DECREF(item);
Py_DECREF(number); Py_DECREF(number);
} }
@@ -161,7 +160,7 @@ wxArrayString testArrayStringTypemap(const wxArrayString& arr);
// Code to convert a wxArrayInt to a Python list of integers. // Code to convert a wxArrayInt to a Python list of integers.
PyObject* list = PyList_New(0); PyObject* list = PyList_New(0);
for (size_t i=0; i < sipCpp->GetCount(); i++) { for (size_t i=0; i < sipCpp->GetCount(); i++) {
PyObject* number = PyInt_FromLong(sipCpp->Item(i)); PyObject* number = wxPyInt_FromLong(sipCpp->Item(i));
PyList_Append(list, number); PyList_Append(list, number);
Py_DECREF(number); Py_DECREF(number);
} }

View File

@@ -130,15 +130,15 @@ void wxPyCoreModuleInject(PyObject* moduleDict)
// TODO: Find some blackmagic way to deprecate wx.Platform such that it raises // TODO: Find some blackmagic way to deprecate wx.Platform such that it raises
// a wraning when used... Maybe a class that returns wx.Port for any __getattr__? // a wraning when used... Maybe a class that returns wx.Port for any __getattr__?
PyDict_SetItemString(moduleDict, "Port", PyString_FromString(wxPort)); PyDict_SetItemString(moduleDict, "Port", PyUnicode_FromString(wxPort));
PyDict_SetItemString(moduleDict, "Platform", PyString_FromString(wxPort)); PyDict_SetItemString(moduleDict, "Platform", PyUnicode_FromString(wxPort));
// Make a tuple of strings that gives more info about the platform and build. // Make a tuple of strings that gives more info about the platform and build.
PyObject* PlatformInfo = PyList_New(0); PyObject* PlatformInfo = PyList_New(0);
PyObject* obj; PyObject* obj;
#define _AddInfoString(st) \ #define _AddInfoString(st) \
obj = PyString_FromString(st); \ obj = PyUnicode_FromString(st); \
PyList_Append(PlatformInfo, obj); \ PyList_Append(PlatformInfo, obj); \
Py_DECREF(obj) Py_DECREF(obj)

View File

@@ -1,26 +1,26 @@
# Load version numbers from __version__... Ensure that major and minor
# versions are the same for both wxPython and wxWidgets.
if 'wxEVT_NULL' in dir():
from wx.__version__ import *
import wx._core
__version__ = VERSION_STRING
assert MAJOR_VERSION == wx._core.MAJOR_VERSION, "wxPython/wxWidgets version mismatch"
assert MINOR_VERSION == wx._core.MINOR_VERSION, "wxPython/wxWidgets version mismatch"
if RELEASE_NUMBER != wx._core.RELEASE_NUMBER:
import warnings
warnings.warn("wxPython/wxWidgets release number mismatch")
del wx._core
else:
Port = ''
Platform = ''
PlatformInfo = []
# A little trick to make 'wx' be a reference to this module so wx.Names can # A little trick to make 'wx' be a reference to this module so wx.Names can
# be used in the python code here. # be used in the python code here.
import sys as _sys import sys as _sys
wx = _sys.modules[__name__] wx = _sys.modules[__name__]
# Load version numbers from __version__... Ensure that major and minor
# versions are the same for both wxPython and wxWidgets.
if 'wxEVT_NULL' in dir():
from __version__ import *
import _core
__version__ = VERSION_STRING
assert MAJOR_VERSION == _core.MAJOR_VERSION, "wxPython/wxWidgets version mismatch"
assert MINOR_VERSION == _core.MINOR_VERSION, "wxPython/wxWidgets version mismatch"
if RELEASE_NUMBER != _core.RELEASE_NUMBER:
import warnings
warnings.warn("wxPython/wxWidgets release number mismatch")
del _core
else:
Port = ''
Platform = ''
PlatformInfo = []
import warnings import warnings
class wxPyDeprecationWarning(DeprecationWarning): class wxPyDeprecationWarning(DeprecationWarning):
@@ -29,6 +29,7 @@ class wxPyDeprecationWarning(DeprecationWarning):
warnings.simplefilter('default', wxPyDeprecationWarning) warnings.simplefilter('default', wxPyDeprecationWarning)
del warnings del warnings
def deprecated(item, msg=''): def deprecated(item, msg=''):
""" """
Create a delegating wrapper that raises a deprecation warning. Can be Create a delegating wrapper that raises a deprecation warning. Can be
@@ -86,7 +87,7 @@ def deprecated(item, msg=''):
else: else:
return DepGetProp(item, msg) return DepGetProp(item, msg)
else: else:
raise TypeError, "unsupported type %s" % type(item) raise TypeError("unsupported type %s" % type(item))
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------

View File

@@ -122,9 +122,9 @@ public:
%ConvertToTypeCode %ConvertToTypeCode
// Code to test a PyObject for compatibility // Code to test a PyObject for compatibility
if (!sipIsErr) { if (!sipIsErr) {
return PyLong_Check(sipPy) || PyInt_Check(sipPy); return PyLong_Check(sipPy) || wxPyInt_Check(sipPy);
} }
if (PyLong_Check(sipPy) || PyInt_Check(sipPy)) if (PyLong_Check(sipPy) || wxPyInt_Check(sipPy))
*sipCppPtrV = (wxPyLongPtr)PyLong_AsVoidPtr(sipPy); *sipCppPtrV = (wxPyLongPtr)PyLong_AsVoidPtr(sipPy);
return sipGetState(sipTransferObj); return sipGetState(sipTransferObj);

View File

@@ -42,44 +42,11 @@ void wxPyCallback::EventThunker(wxEvent& event) {
wxPyBlock_t blocked = wxPyBeginBlockThreads(); wxPyBlock_t blocked = wxPyBeginBlockThreads();
wxString className = event.GetClassInfo()->GetClassName(); wxString className = event.GetClassInfo()->GetClassName();
arg = wxPyConstructObject((void*)&event, className);
// // If the event is one of these types then pass the original
// // event object instead of the one passed to us.
// if ( className == wxT("wxPyEvent") ) {
// arg = ((wxPyEvent*)&event)->GetSelf();
// checkSkip = ((wxPyEvent*)&event)->GetCloned();
// }
// else if ( className == wxT("wxPyCommandEvent") ) {
// arg = ((wxPyCommandEvent*)&event)->GetSelf();
// checkSkip = ((wxPyCommandEvent*)&event)->GetCloned();
// }
// else {
arg = wxPyConstructObject((void*)&event, className);
// }
if (!arg) { if (!arg) {
PyErr_Print(); PyErr_Print();
} else { } else {
// // "intern" the pre/post method names to speed up the HasAttr
// static PyObject* s_preName = NULL;
// static PyObject* s_postName = NULL;
// if (s_preName == NULL) {
// s_preName = PyString_FromString(wxPy_PRECALLINIT);
// s_postName = PyString_FromString(wxPy_POSTCALLCLEANUP);
// }
// // Check if the event object needs some preinitialization
// if (PyObject_HasAttr(arg, s_preName)) {
// result = PyObject_CallMethodObjArgs(arg, s_preName, arg, NULL);
// if ( result ) {
// Py_DECREF(result); // result is ignored, but we still need to decref it
// PyErr_Clear(); // Just in case...
// } else {
// PyErr_Print();
// }
// }
// Call the event handler, passing the event object // Call the event handler, passing the event object
tuple = PyTuple_New(1); tuple = PyTuple_New(1);
PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg
@@ -90,30 +57,6 @@ void wxPyCallback::EventThunker(wxEvent& event) {
} else { } else {
PyErr_Print(); PyErr_Print();
} }
// // Check if the event object needs some post cleanup
// if (PyObject_HasAttr(arg, s_postName)) {
// result = PyObject_CallMethodObjArgs(arg, s_postName, arg, NULL);
// if ( result ) {
// Py_DECREF(result); // result is ignored, but we still need to decref it
// PyErr_Clear(); // Just in case...
// } else {
// PyErr_Print();
// }
// }
// if ( checkSkip ) {
// // if the event object was one of our special types and
// // it had been cloned, then we need to extract the Skipped
// // value from the original and set it in the clone.
// result = PyObject_CallMethod(arg, "GetSkipped", "");
// if ( result ) {
// event.Skip(PyInt_AsLong(result));
// Py_DECREF(result);
// } else {
// PyErr_Print();
// }
// }
Py_DECREF(tuple); Py_DECREF(tuple);
} }
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);

View File

@@ -94,13 +94,13 @@ protected:
Py_DECREF(arglist); Py_DECREF(arglist);
size_t o = 0; size_t o = 0;
if ((result != NULL) && PyString_Check(result)) { if ((result != NULL) && PyBytes_Check(result)) {
o = PyString_Size(result); o = PyBytes_Size(result);
if (o == 0) if (o == 0)
m_lasterror = wxSTREAM_EOF; m_lasterror = wxSTREAM_EOF;
if (o > bufsize) if (o > bufsize)
o = bufsize; o = bufsize;
memcpy((char*)buffer, PyString_AsString(result), o); // strings only, not unicode... memcpy((char*)buffer, PyBytes_AsString(result), o); // strings only, not unicode...
Py_DECREF(result); Py_DECREF(result);
} }
@@ -125,9 +125,9 @@ protected:
// wxFileOffset is a 64-bit value... // wxFileOffset is a 64-bit value...
PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off)); PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
else else
PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off)); PyTuple_SET_ITEM(arglist, 0, wxPyInt_FromLong(off));
PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode)); PyTuple_SET_ITEM(arglist, 1, wxPyInt_FromLong(mode));
PyObject* result = PyEval_CallObject(m_seek, arglist); PyObject* result = PyEval_CallObject(m_seek, arglist);
@@ -148,7 +148,7 @@ protected:
if (PyLong_Check(result)) if (PyLong_Check(result))
o = PyLong_AsLongLong(result); o = PyLong_AsLongLong(result);
else else
o = PyInt_AsLong(result); o = wxPyInt_AsLong(result);
Py_DECREF(result); Py_DECREF(result);
}; };
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);

View File

@@ -96,7 +96,7 @@ protected:
wxPyBlock_t blocked = wxPyBeginBlockThreads(); wxPyBlock_t blocked = wxPyBeginBlockThreads();
PyObject* arglist = PyTuple_New(1); PyObject* arglist = PyTuple_New(1);
PyTuple_SET_ITEM(arglist, 0, PyString_FromStringAndSize((char*)buffer, bufsize)); PyTuple_SET_ITEM(arglist, 0, PyBytes_FromStringAndSize((char*)buffer, bufsize));
PyObject* result = PyEval_CallObject(m_write, arglist); PyObject* result = PyEval_CallObject(m_write, arglist);
Py_DECREF(arglist); Py_DECREF(arglist);
@@ -118,9 +118,9 @@ protected:
// wxFileOffset is a 64-bit value... // wxFileOffset is a 64-bit value...
PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off)); PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
else else
PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off)); PyTuple_SET_ITEM(arglist, 0, wxPyInt_FromLong(off));
PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode)); PyTuple_SET_ITEM(arglist, 1, wxPyInt_FromLong(mode));
PyObject* result = PyEval_CallObject(m_seek, arglist); PyObject* result = PyEval_CallObject(m_seek, arglist);
@@ -141,7 +141,7 @@ protected:
if (PyLong_Check(result)) if (PyLong_Check(result))
o = PyLong_AsLongLong(result); o = PyLong_AsLongLong(result);
else else
o = PyInt_AsLong(result); o = wxPyInt_AsLong(result);
Py_DECREF(result); Py_DECREF(result);
}; };
wxPyEndBlockThreads(blocked); wxPyEndBlockThreads(blocked);

View File

@@ -25,14 +25,14 @@
%ConvertToTypeCode %ConvertToTypeCode
// Code to test a PyObject for compatibility with wxString // Code to test a PyObject for compatibility with wxString
if (!sipIsErr) { if (!sipIsErr) {
if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
// Code to convert a compatible PyObject to a wxString // Code to convert a compatible PyObject to a wxString
PyObject* uni = sipPy; PyObject* uni = sipPy;
if (PyString_Check(sipPy)) { if (PyBytes_Check(sipPy)) {
// if it's a string object convert it to unicode first, assuming utf-8 // if it's a string object convert it to unicode first, assuming utf-8
uni = PyUnicode_FromEncodedObject(sipPy, "utf-8", "strict"); uni = PyUnicode_FromEncodedObject(sipPy, "utf-8", "strict");
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
@@ -43,10 +43,9 @@
*sipCppPtr = new wxString(); *sipCppPtr = new wxString();
size_t len = PyUnicode_GET_SIZE(uni); size_t len = PyUnicode_GET_SIZE(uni);
if (len) { if (len) {
PyUnicode_AsWideChar((PyUnicodeObject*)uni, wxPyUnicode_AsWideChar(uni, wxStringBuffer(**sipCppPtr, len), len);
wxStringBuffer(**sipCppPtr, len), len);
} }
if (PyString_Check(sipPy)) if (PyBytes_Check(sipPy))
Py_DECREF(uni); // release the temporary Unicode object we created Py_DECREF(uni); // release the temporary Unicode object we created
return sipGetState(sipTransferObj); return sipGetState(sipTransferObj);
%End %End
@@ -62,10 +61,10 @@
// Used just for testing the MappedType code, it can be removed later // Used just for testing the MappedType code, it can be removed later
%ModuleCode %ModuleCode
wxString _testStringTypemap(const wxString& str) wxString testStringTypemap(const wxString& str)
{ {
wxString local = str; wxString local = str;
return local; return local;
} }
%End %End
wxString _testStringTypemap(const wxString& str); wxString testStringTypemap(const wxString& str);

View File

@@ -16,9 +16,9 @@
%ConvertToTypeCode %ConvertToTypeCode
// Code to test a PyObject for compatibility // Code to test a PyObject for compatibility
if (!sipIsErr) { if (!sipIsErr) {
if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
return TRUE; return TRUE;
else if (PyInt_Check(sipPy) || PyLong_Check(sipPy)) else if (wxPyInt_Check(sipPy) || PyLong_Check(sipPy))
return TRUE; return TRUE;
else if (PyBool_Check(sipPy)) else if (PyBool_Check(sipPy))
return TRUE; return TRUE;
@@ -30,7 +30,7 @@
// Code to create a new wxPyUserData from the PyObject // Code to create a new wxPyUserData from the PyObject
wxVariant* data = new wxVariant(); wxVariant* data = new wxVariant();
if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) { if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) {
// TODO: Can we just reuse the code in string.sip somehow? // TODO: Can we just reuse the code in string.sip somehow?
// TODO: check state or iserr? // TODO: check state or iserr?
@@ -38,8 +38,8 @@
wxString* strPtr = (wxString*)sipConvertToType(sipPy, sipType_wxString, NULL, SIP_NOT_NONE, NULL, &iserr); wxString* strPtr = (wxString*)sipConvertToType(sipPy, sipType_wxString, NULL, SIP_NOT_NONE, NULL, &iserr);
*data = *strPtr; *data = *strPtr;
} }
else if (PyInt_Check(sipPy)) else if (wxPyInt_Check(sipPy))
*data = (long)PyInt_AS_LONG(sipPy); *data = (long)wxPyInt_AS_LONG(sipPy);
else if (PyLong_Check(sipPy)) else if (PyLong_Check(sipPy))
*data = (long)PyLong_AsLong(sipPy); *data = (long)PyLong_AsLong(sipPy);
else if (PyBool_Check(sipPy)) { else if (PyBool_Check(sipPy)) {

View File

@@ -102,6 +102,35 @@ inline PyObject* wxPyMakeBuffer(void* ptr, Py_ssize_t len) {
} }
// Macros to work around differences in the Python 3 API
#if PY_MAJOR_VERSION >= 3
#define wxPyInt_Check PyLong_Check
#define wxPyInt_AsLong PyLong_AsLong
#define wxPyInt_AS_LONG PyLong_AS_LONG
#define wxPyInt_AsSsize_t PyLong_AsSsize_t
#define wxPyInt_FromLong PyLong_FromLong
#define wxPyNumber_Int PyNumber_Long
#else
#define wxPyInt_Check PyInt_Check
#define wxPyInt_AsLong PyInt_AsLong
#define wxPyInt_AS_LONG PyInt_AS_LONG
#define wxPyInt_AsLong PyInt_AsLong
#define wxPyInt_AsSsize_t PyInt_AsSsize_t
#define wxPyInt_FromLong PyInt_FromLong
#define wxPyNumber_Int PyNumber_Int
#endif
inline
Py_ssize_t wxPyUnicode_AsWideChar(PyObject* unicode, wchar_t* w, Py_ssize_t size)
{
#if PY_MAJOR_VERSION >= 3
return PyUnicode_AsWideChar(unicode, w, size);
#else
return PyUnicode_AsWideChar((PyUnicodeObject*)unicode, w, size);
#endif
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// These are the API items whose implementation can not or should not be // These are the API items whose implementation can not or should not be
// inline functions or macros. The implementations will instead be accessed // inline functions or macros. The implementations will instead be accessed
@@ -117,14 +146,18 @@ struct wxPyAPI {
// Always add new items here at the end. // Always add new items here at the end.
}; };
inline wxPyAPI* wxPyGetAPIPtr() inline wxPyAPI* wxPyGetAPIPtr()
{ {
static wxPyAPI* wxPyAPIPtr = NULL; static wxPyAPI* wxPyAPIPtr = NULL;
if (wxPyAPIPtr == NULL) { if (wxPyAPIPtr == NULL) {
wxPyAPIPtr = (wxPyAPI*)PyCObject_Import("wx._core", "_wxPyAPI"); wxPyAPIPtr = (wxPyAPI*)PyCapsule_Import("wx._wxPyAPI", 0);
// uncomment if needed for debugging
//if (PyErr_Occurred()) { PyErr_Print(); }
//wxASSERT_MSG(wxPyAPIPtr != NULL, wxT("wxPyAPIPtr is NULL!!!"));
} }
// wxASSERT_MSG(wxPyAPIPtr != NULL, wxT("wxPyAPIPtr is NULL!!!")); // uncomment when needed for debugging
return wxPyAPIPtr; return wxPyAPIPtr;
} }
@@ -147,6 +180,7 @@ inline PyObject* wxPyConstructObject(void* ptr, const wxString& className, bool
// manipulations, PyDECREF's and etc. should be wrapped in calls to these functions: // manipulations, PyDECREF's and etc. should be wrapped in calls to these functions:
inline wxPyBlock_t wxPyBeginBlockThreads() inline wxPyBlock_t wxPyBeginBlockThreads()
{ return wxPyGetAPIPtr()->p_wxPyBeginBlockThreads(); } { return wxPyGetAPIPtr()->p_wxPyBeginBlockThreads(); }
inline void wxPyEndBlockThreads(wxPyBlock_t blocked) inline void wxPyEndBlockThreads(wxPyBlock_t blocked)
{ wxPyGetAPIPtr()->p_wxPyEndBlockThreads(blocked); } { wxPyGetAPIPtr()->p_wxPyEndBlockThreads(blocked); }

View File

@@ -28,7 +28,7 @@
static wxString i_Py2wxString(PyObject* source) static wxString i_Py2wxString(PyObject* source)
{ {
PyObject* uni = source; PyObject* uni = source;
if (PyString_Check(source)) { if (PyBytes_Check(source)) {
// if it's a string object convert it to unicode first, assumes utf-8 // if it's a string object convert it to unicode first, assumes utf-8
uni = PyUnicode_FromEncodedObject(source, "utf-8", "strict"); uni = PyUnicode_FromEncodedObject(source, "utf-8", "strict");
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
@@ -37,7 +37,11 @@ static wxString i_Py2wxString(PyObject* source)
} }
} }
else if (!PyUnicode_Check(source)) { else if (!PyUnicode_Check(source)) {
#if PY_MAJOR_VERSION >= 3
uni = PyObject_Str(source);
#else
uni = PyObject_Unicode(source); uni = PyObject_Unicode(source);
#endif
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
PyErr_Clear(); PyErr_Clear();
return wxEmptyString; return wxEmptyString;
@@ -46,8 +50,7 @@ static wxString i_Py2wxString(PyObject* source)
wxString target; wxString target;
size_t len = PyUnicode_GET_SIZE(uni); size_t len = PyUnicode_GET_SIZE(uni);
if (len) { if (len) {
PyUnicode_AsWideChar((PyUnicodeObject*)uni, wxPyUnicode_AsWideChar(uni, wxStringBuffer(target, len), len);
wxStringBuffer(target, len), len);
} }
if (!PyUnicode_Check(source)) if (!PyUnicode_Check(source))
Py_DECREF(uni); // release the temporary Unicode object we created Py_DECREF(uni); // release the temporary Unicode object we created
@@ -61,7 +64,7 @@ static wxString i_Py2wxString(PyObject* source)
//inline wxString Py2wxString(PyObject* obj, bool setException=false, int& isErr=0) { //inline wxString Py2wxString(PyObject* obj, bool setException=false, int& isErr=0) {
// wxString str; // wxString str;
// PyObject* uni = obj; // PyObject* uni = obj;
// if (PyString_Check(obj)) { // if (PyBytes_Check(obj)) {
// // if it's a string object convert it to unicode first, assuming utf-8 // // if it's a string object convert it to unicode first, assuming utf-8
// uni = PyUnicode_FromEncodedObject(sipPy, "utf-8", "strict"); // uni = PyUnicode_FromEncodedObject(sipPy, "utf-8", "strict");
// if (PyErr_Occurred()) { // if (PyErr_Occurred()) {
@@ -77,7 +80,7 @@ static wxString i_Py2wxString(PyObject* source)
// // TODO: Coerce non-unicode types to unicode here? (Classic does) // // TODO: Coerce non-unicode types to unicode here? (Classic does)
// size_t len = PyUnicode_GET_SIZE(uni); // size_t len = PyUnicode_GET_SIZE(uni);
// if (len) { // if (len) {
// PyUnicode_AsWideChar((PyUnicodeObject*)uni, wxStringBuffer(str, len), len); // wxPyUnicode_AsWideChar(uni, wxStringBuffer(str, len), len);
// } // }
// if (obj != uni) // if (obj != uni)
// Py_DECREF(uni) // release the temporary Unicode object we may have created // Py_DECREF(uni) // release the temporary Unicode object we may have created
@@ -130,12 +133,15 @@ static wxPyAPI API = {
%End %End
// Code that will run when _core is imported that will stash away a pointer %PostInitialisationCode
// to the structure. // Code that will run when _core is imported that will stash away a
%InitialisationCode // pointer to the API structure.
PyObject* cobj = PyCObject_FromVoidPtr(&API, NULL); PyObject* wxmod = PyImport_ImportModule("wx");
PyDict_SetItemString(sipModuleDict, "_wxPyAPI", cobj); PyObject* wxmodDict = PyModule_GetDict(wxmod);
Py_XDECREF(cobj); PyObject* apiObj = PyCapsule_New(&API, "wx._wxPyAPI", NULL);
PyDict_SetItemString(wxmodDict, "_wxPyAPI", apiObj);
Py_XDECREF(apiObj);
Py_DECREF(wxmod);
wxPyGetAPIPtr(); wxPyGetAPIPtr();
%End %End

View File

@@ -1,9 +1,9 @@
import sys import sys
if '--stdout' in sys.argv: if '--stdout' in sys.argv:
print 'process_test' print('process_test')
if '--echo' in sys.argv: if '--echo' in sys.argv:
text = raw_input() text = raw_input()
print "I read '%s'" % text print("I read '%s'" % text)
sys.exit(0) sys.exit(0)

View File

@@ -14,9 +14,9 @@ sys.path.insert(0, phoenixDir)
# stuff for debugging # stuff for debugging
import wx import wx
print "wx.version:", wx.version() print("wx.version: " + wx.version())
print "pid:", os.getpid() print("pid: " + str(os.getpid()))
#print "executable:", sys.executable; raw_input("Press Enter...") #print("executable: " + sys.executable); raw_input("Press Enter...")
import imp_unittest, unittest import imp_unittest, unittest

View File

@@ -10,7 +10,7 @@ class aboutdlg_Tests(wtc.WidgetTestCase):
def _makeInfo(self): def _makeInfo(self):
info = wx.adv.AboutDialogInfo() info = wx.adv.AboutDialogInfo()
info.SetVersion('1.2.3') info.SetVersion('1.2.3')
info.SetName('My Goofy App') info.SetName('My Goofy AboutBox Test')
info.SetDevelopers(['Goofy', 'Mickey', 'Donald']) info.SetDevelopers(['Goofy', 'Mickey', 'Donald'])
info.SetDescription('This is a very goofy application') info.SetDescription('This is a very goofy application')
info.SetCopyright('(c) by Goofy Enterprises, Inc.') info.SetCopyright('(c) by Goofy Enterprises, Inc.')

View File

@@ -1,25 +1,32 @@
import imp_unittest, unittest import imp_unittest, unittest
import wx import wx
import wtc
import sys
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
if not wtc.isPython3():
alt = unicode
else:
def alt(s):
return bytes(s, 'utf-8')
class ArrayString(unittest.TestCase): class ArrayString(unittest.TestCase):
if hasattr(wx, 'testArrayStringTypemap'): if hasattr(wx, 'testArrayStringTypemap'):
def test_ArrayStringTypemaps(self): def test_ArrayStringTypemaps(self):
# basic conversion of list or tuples of strings # basic conversion of list or tuples of strings
seqList = ['a', u'b', 'hello world'] seqList = ['a', alt('b'), 'hello world']
self.assertEqual(wx.testArrayStringTypemap(seqList), seqList) self.assertEqual(wx.testArrayStringTypemap(seqList), ['a', 'b', 'hello world'])
seqTuple = ('a', u'b', 'hello world') seqTuple = ('a', alt('b'), 'hello world')
self.assertEqual(wx.testArrayStringTypemap(seqTuple), list(seqTuple)) self.assertEqual(wx.testArrayStringTypemap(seqTuple), ['a', 'b', 'hello world'])
def test_ArrayStringTypemapErrors(self): def test_ArrayStringTypemapErrors(self):
# test error conditions # test error conditions
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
wx.testArrayStringTypemap("STRING sequence") wx.testArrayStringTypemap("STRING sequence")
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
wx.testArrayStringTypemap(u"UNICODE sequence") wx.testArrayStringTypemap(alt("ALT sequence"))
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
wx.testArrayStringTypemap(["list", "with", "non-string", "items", 123]) wx.testArrayStringTypemap(["list", "with", "non-string", "items", 123])

View File

@@ -57,7 +57,10 @@ class BitmapTests(wtc.WidgetTestCase):
self.assertTrue( not b1.IsOk() ) self.assertTrue( not b1.IsOk() )
b2 = wx.Bitmap(5, 10, 24) b2 = wx.Bitmap(5, 10, 24)
self.assertTrue( b2.IsOk() ) self.assertTrue( b2.IsOk() )
self.assertTrue( b2.__nonzero__() == b2.IsOk() ) if wtc.isPython3():
self.assertTrue( b2.__bool__() == b2.IsOk() )
else:
self.assertTrue( b2.__nonzero__() == b2.IsOk() )
# check that the __nonzero__ method can be used with if satements # check that the __nonzero__ method can be used with if satements
nzcheck = False nzcheck = False

View File

@@ -36,9 +36,14 @@ class cmndata_tests(wtc.WidgetTestCase):
pd = wx.PrintData() pd = wx.PrintData()
pdd = wx.PrintDialogData() pdd = wx.PrintDialogData()
psdd.__nonzero__() if wtc.isPython3():
pd.__nonzero__() psdd.__bool__()
pdd.__nonzero__() pd.__bool__()
pdd.__bool__()
else:
psdd.__nonzero__()
pd.__nonzero__()
pdd.__nonzero__()
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -69,7 +69,10 @@ class CursorTests(wtc.WidgetTestCase):
c2 = wx.Cursor(wx.CURSOR_ARROW) c2 = wx.Cursor(wx.CURSOR_ARROW)
self.assertTrue( c2.IsOk() ) self.assertTrue( c2.IsOk() )
self.assertTrue( c2.__nonzero__() == c2.IsOk() ) if wtc.isPython3():
self.assertTrue( c2.__bool__() == c2.IsOk() )
else:
self.assertTrue( c2.__nonzero__() == c2.IsOk() )
# check that the __nonzero__ method can be used with if satements # check that the __nonzero__ method can be used with if satements
nzcheck = False nzcheck = False

View File

@@ -68,7 +68,7 @@ class DataObjTests(wtc.WidgetTestCase):
def __init__(self, value=''): def __init__(self, value=''):
wx.DataObject.__init__(self) wx.DataObject.__init__(self)
self.myFormats = [wx.DataFormat(wx.DF_TEXT)] self.myFormats = [wx.DataFormat(wx.DF_TEXT)]
self.myData = bytes(value) self.myData = wtc.mybytes(value)
def GetAllFormats(self, d): def GetAllFormats(self, d):
return self.myFormats return self.myFormats
@@ -120,7 +120,7 @@ class DataObjTests(wtc.WidgetTestCase):
def __init__(self, value=''): def __init__(self, value=''):
wx.DataObjectSimple.__init__(self) wx.DataObjectSimple.__init__(self)
self.SetFormat(wx.DataFormat(wx.DF_TEXT)) self.SetFormat(wx.DataFormat(wx.DF_TEXT))
self.myData = bytes(value) self.myData = wtc.mybytes(value)
def GetDataSize(self): def GetDataSize(self):
return len(self.myData) return len(self.myData)
@@ -155,11 +155,11 @@ class DataObjTests(wtc.WidgetTestCase):
def test_CustomDataObject(self): def test_CustomDataObject(self):
import pickle import pickle
data1 = range(10) data1 = list(range(10))
obj = wx.CustomDataObject('my custom format') obj = wx.CustomDataObject('my custom format')
obj.SetData(pickle.dumps(data1)) obj.SetData(pickle.dumps(data1))
data2 = pickle.loads(obj.GetData().tobytes()) data2 = pickle.loads(obj.GetData().tobytes())
self.assertTrue(data1 == data2) self.assertEqual(data1, data2)

View File

@@ -1,7 +1,7 @@
import imp_unittest, unittest import imp_unittest, unittest
import wtc import wtc
import wx import wx
import os; print os.getpid() #import os; print(os.getpid())
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -39,7 +39,7 @@ class dnd_Tests(wtc.WidgetTestCase):
if 'wxGTK' in wx.PlatformInfo: if 'wxGTK' in wx.PlatformInfo:
ds.SetIcon(wx.DragCopy, wx.Icon(icoFile)) ds.SetIcon(wx.DragCopy, wx.Icon(icoFile))
else: else:
ds.SetCursor(wx.DragCopy, wx.Cursor(curFile)) ds.SetCursor(wx.DragCopy, wx.Cursor(curFile, wx.BITMAP_TYPE_CUR))
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -2,7 +2,6 @@ import imp_unittest, unittest
import wtc import wtc
import wx import wx
import os import os
from cStringIO import StringIO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -2,6 +2,10 @@ import imp_unittest, unittest
import wtc import wtc
import wx import wx
import os import os
if wtc.isPython3():
from io import BytesIO as FileLikeObject
else:
from cStringIO import StringIO as FileLikeObject
pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png') pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png')
@@ -75,16 +79,16 @@ class image_Tests(wtc.WidgetTestCase):
self.assertTrue(img.IsOk()) self.assertTrue(img.IsOk())
def test_imageCtor8(self): def test_imageCtor8(self):
data = open(pngFile, 'rb').read() with open(pngFile, 'rb') as f:
import StringIO data = f.read()
stream = StringIO.StringIO(data) stream = FileLikeObject(data)
img = wx.Image(stream, wx.BITMAP_TYPE_PNG) img = wx.Image(stream, wx.BITMAP_TYPE_PNG)
self.assertTrue(img.IsOk()) self.assertTrue(img.IsOk())
def test_imageCtor9(self): def test_imageCtor9(self):
data = open(pngFile, 'rb').read() with open(pngFile, 'rb') as f:
import StringIO data = f.read()
stream = StringIO.StringIO(data) stream = FileLikeObject(data)
img = wx.Image(stream, 'image/png') img = wx.Image(stream, 'image/png')
self.assertTrue(img.IsOk()) self.assertTrue(img.IsOk())
@@ -133,9 +137,9 @@ class image_Tests(wtc.WidgetTestCase):
self.assertTrue(img.IsOk()) self.assertTrue(img.IsOk())
data = img.GetDataBuffer() data = img.GetDataBuffer()
self.assertTrue(isinstance(data, memoryview)) self.assertTrue(isinstance(data, memoryview))
data[0] = '\1' data[0] = b'\1'
data[1] = '\2' data[1] = b'\2'
data[2] = '\3' data[2] = b'\3'
self.assertEqual(1, img.GetRed(0,0)) self.assertEqual(1, img.GetRed(0,0))
self.assertEqual(2, img.GetGreen(0,0)) self.assertEqual(2, img.GetGreen(0,0))
self.assertEqual(3, img.GetBlue(0,0)) self.assertEqual(3, img.GetBlue(0,0))
@@ -147,9 +151,9 @@ class image_Tests(wtc.WidgetTestCase):
self.assertTrue(img.IsOk()) self.assertTrue(img.IsOk())
data = img.GetAlphaBuffer() data = img.GetAlphaBuffer()
self.assertTrue(isinstance(data, memoryview)) self.assertTrue(isinstance(data, memoryview))
data[0] = '\1' data[0] = b'\1'
data[1] = '\2' data[1] = b'\2'
data[2] = '\3' data[2] = b'\3'
self.assertEqual(1, img.GetAlpha(0,0)) self.assertEqual(1, img.GetAlpha(0,0))
self.assertEqual(2, img.GetAlpha(1,0)) self.assertEqual(2, img.GetAlpha(1,0))
self.assertEqual(3, img.GetAlpha(2,0)) self.assertEqual(3, img.GetAlpha(2,0))

View File

@@ -27,9 +27,11 @@ class joystick_Tests(wtc.WidgetTestCase):
wx.EVT_JOY_ZMOVE wx.EVT_JOY_ZMOVE
wx.EVT_JOYSTICK_EVENTS wx.EVT_JOYSTICK_EVENTS
@unittest.expectedFailure
def test_joystick2(self): def test_joystick2(self):
# Creating a Joystick object should fail on Mac. Currently it isn't... # Creating a Joystick object should fail on Mac. Currently it isn't...
# We'll need a new feature added to sip to get it.
if 'wxMac' in wx.PlatformInfo: if 'wxMac' in wx.PlatformInfo:
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
j = wx.adv.Joystick() j = wx.adv.Joystick()

View File

@@ -8,15 +8,17 @@ class mimetype_Tests(wtc.WidgetTestCase):
def test_mimetype1(self): def test_mimetype1(self):
ft = wx.TheMimeTypesManager.GetFileTypeFromExtension('*.pdf') ft = wx.TheMimeTypesManager.GetFileTypeFromExtension('*.pdf')
ft.GetExtensions() if ft:
ft.GetMimeType() ft.GetExtensions()
ft.GetIcon() ft.GetMimeType()
ft.GetIcon()
def test_mimetype2(self): def test_mimetype2(self):
ft = wx.TheMimeTypesManager.GetFileTypeFromMimeType('image/png') ft = wx.TheMimeTypesManager.GetFileTypeFromMimeType('image/png')
ft.GetExtensions() if ft:
ft.GetMimeType() ft.GetExtensions()
ft.GetIcon() ft.GetMimeType()
ft.GetIcon()
def test_mimetype3(self): def test_mimetype3(self):
fti = wx.FileTypeInfo('mime', 'open', 'print', 'desc', 'ext1') fti = wx.FileTypeInfo('mime', 'open', 'print', 'desc', 'ext1')

View File

@@ -7,7 +7,7 @@ import wx
class pickers_Tests(wtc.WidgetTestCase): class pickers_Tests(wtc.WidgetTestCase):
def test_pickersColour(self): def test_pickersColour(self):
p = wx.ColourPickerCtrl(self.frame, col='blue') p = wx.ColourPickerCtrl(self.frame, colour='blue')
self.assertTrue(p.GetColour() == wx.Colour(0, 0, 0xff)) self.assertTrue(p.GetColour() == wx.Colour(0, 0, 0xff))
def test_pickersColourConstants(self): def test_pickersColourConstants(self):

View File

@@ -24,7 +24,8 @@ class sound_Tests(wtc.WidgetTestCase):
def test_sound3(self): def test_sound3(self):
sound = wx.adv.Sound() sound = wx.adv.Sound()
self.assertTrue(not sound.IsOk()) self.assertTrue(not sound.IsOk())
data = open(wavFile, 'rb').read() with open(wavFile, 'rb') as f:
data = f.read()
sound.CreateFromData(data) sound.CreateFromData(data)
self.assertTrue(sound.IsOk()) self.assertTrue(sound.IsOk())
rv = sound.Play(wx.adv.SOUND_SYNC) rv = sound.Play(wx.adv.SOUND_SYNC)

View File

@@ -2,7 +2,10 @@ import imp_unittest, unittest
import wtc import wtc
import wx import wx
import os import os
from cStringIO import StringIO if wtc.isPython3():
from io import BytesIO as FileLikeObject
else:
from cStringIO import StringIO as FileLikeObject
pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png') pngFile = os.path.join(os.path.dirname(__file__), 'toucan.png')
@@ -16,7 +19,9 @@ class stream_Tests(wtc.WidgetTestCase):
# wrapped function expecting a wxInputStream. # wrapped function expecting a wxInputStream.
# First, load the image data into a StringIO object # First, load the image data into a StringIO object
stream = StringIO(open(pngFile, 'rb').read()) f = open(pngFile, 'rb')
stream = FileLikeObject(f.read())
f.close()
# Then use it to create a wx.Image # Then use it to create a wx.Image
img = wx.Image(stream) img = wx.Image(stream)
@@ -27,11 +32,11 @@ class stream_Tests(wtc.WidgetTestCase):
# wrapped function expecting a wxOutputStream. # wrapped function expecting a wxOutputStream.
image = wx.Image(pngFile) image = wx.Image(pngFile)
stream = StringIO() stream = FileLikeObject()
image.SaveFile(stream, wx.BITMAP_TYPE_PNG) image.SaveFile(stream, wx.BITMAP_TYPE_PNG)
del image del image
stream = StringIO(stream.getvalue()) stream = FileLikeObject(stream.getvalue())
image = wx.Image(stream) image = wx.Image(stream)
self.assertTrue(image.IsOk()) self.assertTrue(image.IsOk())

View File

@@ -1,61 +1,89 @@
import imp_unittest, unittest import imp_unittest, unittest
import wx import wx
import wx._core import wtc
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
class String(unittest.TestCase): class String(unittest.TestCase):
if hasattr(wx._core, '_testStringTypemap'): if hasattr(wx, 'testStringTypemap'):
def test_StringTypemaps(self): if not wtc.isPython3():
utf = '\xc3\xa9l\xc3\xa9phant' # utf-8 string def test_StringTypemapsPy2(self):
uni = utf.decode('utf-8') # convert to unicode utf = '\xc3\xa9l\xc3\xa9phant' # utf-8 string
iso = uni.encode('iso-8859-1') # make a string with a different encoding uni = utf.decode('utf-8') # convert to unicode
iso = uni.encode('iso-8859-1') # make a string with a different encoding
# wx._testStringTypemap() will accept a parameter that is a Unicode object
# or an 'ascii' or 'utf-8' string object, which will then be converted to
# a wxString. The return value is a Unicode object that has been
# converted from a wxString that is a copy of the wxString created for
# the parameter.
# ascii
result = wx._core._testStringTypemap('hello')
self.assertTrue(type(result) == unicode)
self.assertTrue(result == u'hello')
# unicode should pass through unmodified
result = wx._core._testStringTypemap(uni)
self.assertTrue(result == uni)
# utf-8 is converted
result = wx._core._testStringTypemap(utf)
self.assertTrue(result == uni)
# can't auto-convert this
with self.assertRaises(UnicodeDecodeError):
result = wx._core._testStringTypemap(iso)
# utf-16-be # wx.testStringTypemap() will accept a parameter that
val = "\x00\xe9\x00l\x00\xe9\x00p\x00h\x00a\x00n\x00t" # is a Unicode object or an 'ascii' or 'utf-8' string object,
with self.assertRaises(UnicodeDecodeError): # which will then be converted to a wxString. The return
result = wx._core._testStringTypemap(val) # value is a Unicode object that has been converted from a
result = wx._core._testStringTypemap( val.decode('utf-16-be')) # wxString that is a copy of the wxString created for the
self.assertTrue(result == uni) # parameter.
# ascii
result = wx.testStringTypemap('hello')
self.assertTrue(type(result) == unicode)
self.assertTrue(result == unicode('hello'))
# unicode should pass through unmodified
result = wx.testStringTypemap(uni)
self.assertTrue(result == uni)
# utf-8 is converted
result = wx.testStringTypemap(utf)
self.assertTrue(result == uni)
# can't auto-convert this
with self.assertRaises(UnicodeDecodeError):
result = wx.testStringTypemap(iso)
# utf-16-be
val = "\x00\xe9\x00l\x00\xe9\x00p\x00h\x00a\x00n\x00t"
with self.assertRaises(UnicodeDecodeError):
result = wx.testStringTypemap(val)
result = wx.testStringTypemap( val.decode('utf-16-be'))
self.assertTrue(result == uni)
# utf-32-be
val = "\x00\x00\x00\xe9\x00\x00\x00l\x00\x00\x00\xe9\x00\x00\x00p\x00\x00\x00h\x00\x00\x00a\x00\x00\x00n\x00\x00\x00t"
with self.assertRaises(UnicodeDecodeError):
result = wx.testStringTypemap(val)
result = wx.testStringTypemap(val.decode('utf-32-be'))
self.assertTrue(result == uni)
# utf-8 with BOM
#val = "\xef\xbb\xbfHello"
#result = wx.testStringTypemap(val)
#self.assertTrue(result == u'\ufeffHello')
else:
def test_StringTypemapsPy3(self):
utf = b'\xc3\xa9l\xc3\xa9phant' # utf-8 bytes
uni = utf.decode('utf-8') # convert to unicode
iso = uni.encode('iso-8859-1') # make a string with a different encoding
# ascii
result = wx.testStringTypemap(b'hello')
self.assertTrue(type(result) == str)
self.assertTrue(result == 'hello')
# unicode should pass through unmodified
result = wx.testStringTypemap(uni)
self.assertTrue(result == uni)
# utf-8 is converted
result = wx.testStringTypemap(utf)
self.assertTrue(result == uni)
# can't auto-convert this
with self.assertRaises(UnicodeDecodeError):
result = wx.testStringTypemap(iso)
# utf-32-be
val = "\x00\x00\x00\xe9\x00\x00\x00l\x00\x00\x00\xe9\x00\x00\x00p\x00\x00\x00h\x00\x00\x00a\x00\x00\x00n\x00\x00\x00t"
with self.assertRaises(UnicodeDecodeError):
result = wx._core._testStringTypemap(val)
result = wx._core._testStringTypemap(val.decode('utf-32-be'))
self.assertTrue(result == uni)
# utf-8 with BOM
val = "\xef\xbb\xbfHello"
result = wx._core._testStringTypemap(val)
self.assertTrue(result == u'\ufeffHello')
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -179,11 +179,11 @@ class uiaction_KeyboardTests(wtc.WidgetTestCase):
def test_uiactionKeyboardKeyDownUp(self): def test_uiactionKeyboardKeyDownUp(self):
uia = wx.UIActionSimulator() uia = wx.UIActionSimulator()
for c in "This is a test": for c in "This is a test":
if c in string.uppercase: if c.isupper():
uia.KeyDown(wx.WXK_SHIFT); self.myYield() uia.KeyDown(wx.WXK_SHIFT); self.myYield()
uia.KeyDown(ord(c)); self.myYield() uia.KeyDown(ord(c)); self.myYield()
uia.KeyUp(ord(c)); self.myYield() uia.KeyUp(ord(c)); self.myYield()
if c in string.uppercase: if c.isupper():
uia.KeyUp(wx.WXK_SHIFT); self.myYield() uia.KeyUp(wx.WXK_SHIFT); self.myYield()
self.myYield() self.myYield()
@@ -194,7 +194,7 @@ class uiaction_KeyboardTests(wtc.WidgetTestCase):
uia = wx.UIActionSimulator() uia = wx.UIActionSimulator()
for c in "This is a test": for c in "This is a test":
mod = wx.MOD_NONE mod = wx.MOD_NONE
if c in string.uppercase: if c.isupper():
mod = wx.MOD_SHIFT mod = wx.MOD_SHIFT
uia.Char(ord(c), mod); self.myYield() uia.Char(ord(c), mod); self.myYield()
self.myYield() self.myYield()

View File

@@ -15,7 +15,11 @@ class WindowTests(wtc.WidgetTestCase):
def test_windowHandle(self): def test_windowHandle(self):
w = wx.Window(self.frame, -1, (10,10), (50,50)) w = wx.Window(self.frame, -1, (10,10), (50,50))
hdl = w.GetHandle() hdl = w.GetHandle()
self.assertTrue(isinstance(hdl, (int, long))) if wtc.isPython3():
base = int
else:
base = (int, long)
self.assertTrue(isinstance(hdl, base))
def test_windowProperties(self): def test_windowProperties(self):

View File

@@ -44,8 +44,12 @@ class datetime_Tests(wtc.WidgetTestCase):
def test_datetimeGetAmPm(self): def test_datetimeGetAmPm(self):
am, pm = wx.DateTime.GetAmPmStrings() am, pm = wx.DateTime.GetAmPmStrings()
self.assertTrue(isinstance(am, basestring) and am != "") if wtc.isPython3():
self.assertTrue(isinstance(pm, basestring) and pm != "") base = str
else:
base = unicode
self.assertTrue(isinstance(am, base) and am != "")
self.assertTrue(isinstance(pm, base) and pm != "")
def test_datetimeProperties(self): def test_datetimeProperties(self):

View File

@@ -1,5 +1,6 @@
import imp_unittest, unittest import imp_unittest, unittest
import wx import wx
import sys
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -66,6 +67,20 @@ class WidgetTestCase(unittest.TestCase):
break break
intervals -= 1 intervals -= 1
#---------------------------------------------------------------------------
def isPython3():
return sys.version_info[0] >= 3
def mybytes(text):
if isPython3():
return bytes(text, 'utf-8')
else:
return str(text)
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------