diff --git a/ez_setup.py b/ez_setup.py deleted file mode 100644 index d24e845..0000000 --- a/ez_setup.py +++ /dev/null @@ -1,276 +0,0 @@ -#!python -"""Bootstrap setuptools installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from ez_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import sys -DEFAULT_VERSION = "0.6c9" -DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] - -md5_data = { - 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', - 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', - 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', - 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', - 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', - 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', - 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', - 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', - 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', - 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', - 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', - 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', - 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', - 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', - 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', - 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', - 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', - 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', - 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', - 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', - 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', - 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', - 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', - 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', - 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', - 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', - 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', - 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', - 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', - 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', - 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', - 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', - 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', - 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', -} - -import sys, os -try: from hashlib import md5 -except ImportError: from md5 import md5 - -def _validate_md5(egg_name, data): - if egg_name in md5_data: - digest = md5(data).hexdigest() - if digest != md5_data[egg_name]: - print >>sys.stderr, ( - "md5 validation of %s failed! (Possible download problem?)" - % egg_name - ) - sys.exit(2) - return data - -def use_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - download_delay=15 -): - """Automatically find/download setuptools and make it available on sys.path - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end with - a '/'). `to_dir` is the directory where setuptools will be downloaded, if - it is not already available. If `download_delay` is specified, it should - be the number of seconds that will be paused before initiating a download, - should one be required. If an older version of setuptools is installed, - this routine will print a message to ``sys.stderr`` and raise SystemExit in - an attempt to abort the calling script. - """ - was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules - def do_download(): - egg = download_setuptools(version, download_base, to_dir, download_delay) - sys.path.insert(0, egg) - import setuptools; setuptools.bootstrap_install_from = egg - try: - import pkg_resources - except ImportError: - return do_download() - try: - pkg_resources.require("setuptools>="+version); return - except pkg_resources.VersionConflict, e: - if was_imported: - print >>sys.stderr, ( - "The required version of setuptools (>=%s) is not available, and\n" - "can't be installed while this script is running. Please install\n" - " a more recent version first, using 'easy_install -U setuptools'." - "\n\n(Currently using %r)" - ) % (version, e.args[0]) - sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return do_download() - except pkg_resources.DistributionNotFound: - return do_download() - -def download_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - delay = 15 -): - """Download setuptools from a specified location and return its filename - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download attempt. - """ - import urllib2, shutil - egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) - url = download_base + egg_name - saveto = os.path.join(to_dir, egg_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - from distutils import log - if delay: - log.warn(""" ---------------------------------------------------------------------------- -This script requires setuptools version %s to run (even to display -help). I will attempt to download it for you (from -%s), but -you may need to enable firewall access for this script first. -I will start the download in %d seconds. - -(Note: if this machine does not have network access, please obtain the file - - %s - -and place it in this directory before rerunning this script.) ----------------------------------------------------------------------------""", - version, download_base, delay, url - ); from time import sleep; sleep(delay) - log.warn("Downloading %s", url) - src = urllib2.urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = _validate_md5(egg_name, src.read()) - dst = open(saveto,"wb"); dst.write(data) - finally: - if src: src.close() - if dst: dst.close() - return os.path.realpath(saveto) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - try: - import setuptools - except ImportError: - egg = None - try: - egg = download_setuptools(version, delay=0) - sys.path.insert(0,egg) - from setuptools.command.easy_install import main - return main(list(argv)+[egg]) # we're done here - finally: - if egg and os.path.exists(egg): - os.unlink(egg) - else: - if setuptools.__version__ == '0.0.1': - print >>sys.stderr, ( - "You have an obsolete version of setuptools installed. Please\n" - "remove it from your system entirely before rerunning this script." - ) - sys.exit(2) - - req = "setuptools>="+version - import pkg_resources - try: - pkg_resources.require(req) - except pkg_resources.VersionConflict: - try: - from setuptools.command.easy_install import main - except ImportError: - from easy_install import main - main(list(argv)+[download_setuptools(delay=0)]) - sys.exit(0) # try to force an exit - else: - if argv: - from setuptools.command.easy_install import main - main(argv) - else: - print "Setuptools version",version,"or greater has been installed." - print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' - -def update_md5(filenames): - """Update our built-in md5 registry""" - - import re - - for name in filenames: - base = os.path.basename(name) - f = open(name,'rb') - md5_data[base] = md5(f.read()).hexdigest() - f.close() - - data = [" %r: %r,\n" % it for it in md5_data.items()] - data.sort() - repl = "".join(data) - - import inspect - srcfile = inspect.getsourcefile(sys.modules[__name__]) - f = open(srcfile, 'rb'); src = f.read(); f.close() - - match = re.search("\nmd5_data = {\n([^}]+)}", src) - if not match: - print >>sys.stderr, "Internal error!" - sys.exit(2) - - src = src[:match.start(1)] + repl + src[match.end(1):] - f = open(srcfile,'w') - f.write(src) - f.close() - - -if __name__=='__main__': - if len(sys.argv)>2 and sys.argv[1]=='--md5update': - update_md5(sys.argv[2:]) - else: - main(sys.argv[1:]) - - - - - - diff --git a/setup.py b/setup.py index dabb917..d6b462c 100644 --- a/setup.py +++ b/setup.py @@ -29,8 +29,6 @@ import subprocess as sp import sys from distutils.dist import Distribution -import ez_setup -ez_setup.use_setuptools() from setuptools import setup, Extension DEBUG = "--debug" in sys.argv @@ -72,7 +70,7 @@ def pkg_config(pkg_name, config=None): "-D": ("extra_compile_args", 0), "-Wl": ("extra_link_args", 0) } - for flag in stdout.split(): + for flag in stdout.decode().split(): for prefix in prefixes: if not flag.startswith(prefix): continue diff --git a/spidermonkey/context.c b/spidermonkey/context.c index 6db6d83..7df8218 100644 --- a/spidermonkey/context.c +++ b/spidermonkey/context.c @@ -711,8 +711,7 @@ static PyMethodDef Context_methods[] = { }; PyTypeObject _ContextType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey.Context", /*tp_name*/ sizeof(Context), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -768,7 +767,8 @@ Context_has_access(Context* pycx, JSContext* jscx, PyObject* obj, PyObject* key) tpl = Py_BuildValue("(OO)", obj, key); if(tpl == NULL) goto done; - tmp = PyObject_Call(pycx->access, tpl, NULL); + tmp = PyObject_CallObject(pycx->access, tpl); + if(tmp == NULL) goto done; res = PyObject_IsTrue(tmp); done: diff --git a/spidermonkey/convert.c b/spidermonkey/convert.c index 6bfc3cf..12eccb2 100644 --- a/spidermonkey/convert.c +++ b/spidermonkey/convert.c @@ -31,7 +31,7 @@ py2js(Context* cx, PyObject* obj) { return py2js_double(cx, obj); } - else if(PyString_Check(obj) || PyUnicode_Check(obj)) + else if(PyBytes_Check(obj) || PyUnicode_Check(obj)) { return py2js_string(cx, obj); } diff --git a/spidermonkey/error.c b/spidermonkey/error.c index b325a26..f4ccf90 100644 --- a/spidermonkey/error.c +++ b/spidermonkey/error.c @@ -21,10 +21,10 @@ add_frame(const char* srcfile, const char* funcname, int linenum) PyCodeObject* code = NULL; PyFrameObject* frame = NULL; - src = PyString_FromString(srcfile); + src = PyBytes_FromString(srcfile); if(src == NULL) goto error; - func = PyString_FromString(funcname); + func = PyBytes_FromString(funcname); if(func == NULL) goto error; glbl = PyModule_GetDict(SpidermonkeyModule); @@ -33,24 +33,13 @@ add_frame(const char* srcfile, const char* funcname, int linenum) tpl = PyTuple_New(0); if(tpl == NULL) goto error; - str = PyString_FromString(""); + str = PyBytes_FromString(""); if(str == NULL) goto error; - code = PyCode_New( - 0, /*co_argcount*/ - 0, /*co_nlocals*/ - 0, /*co_stacksize*/ - 0, /*co_flags*/ - str, /*co_code*/ - tpl, /*co_consts*/ - tpl, /*co_names*/ - tpl, /*co_varnames*/ - tpl, /*co_freevars*/ - tpl, /*co_cellvars*/ + code = PyCode_NewEmpty( src, /*co_filename*/ func, /*co_name*/ - linenum, /*co_firstlineno*/ - str /*co_lnotab*/ + linenum /*co_firstlineno*/ ); if(code == NULL) goto error; @@ -91,7 +80,7 @@ report_error_cb(JSContext* cx, const char* message, JSErrorReport* report) if(!PyErr_Occurred()) { - PyErr_SetString(JSError, message); + PyErr_SetString(JSError, mesg); } add_frame(srcfile, "JavaScript code", report->lineno); diff --git a/spidermonkey/hashcobj.c b/spidermonkey/hashcobj.c index e53eaf5..c56ae87 100644 --- a/spidermonkey/hashcobj.c +++ b/spidermonkey/hashcobj.c @@ -63,11 +63,45 @@ HashCObj_cmp(PyObject* self, PyObject* other) return ret; } +PyObject* +HashCObj_rich_cmp(PyObject* self, PyObject* other, int op) +{ + PyObject* ret = NULL; + + if(op != Py_EQ && op != Py_NE) return Py_NotImplemented; + + if(!PyObject_TypeCheck(self, HashCObjType)) + { + PyErr_SetString(PyExc_ValueError, "Invalid comparison object."); + goto error; + } + + if(!PyObject_TypeCheck(other, HashCObjType)) + { + PyErr_SetString(PyExc_ValueError, "Invalid comparison object 2."); + goto error; + } + + if(((HashCObj*)self)->cobj == ((HashCObj*)other)->cobj) + { + ret = (op == Py_EQ)? Py_True : Py_False; + } + else + { + ret = (op == Py_EQ)? Py_False : Py_True; + } + +error: +success: + Py_XINCREF(ret); + return ret; +} + PyObject* HashCObj_repr(PyObject* self) { - return PyString_FromFormat("<%s Ptr: %p>", - self->ob_type->tp_name, + return PyBytes_FromFormat("<%s Ptr: %p>", + Py_TYPE(self)->tp_name, ((HashCObj*)self)->cobj); } @@ -78,8 +112,7 @@ HashCObj_hash(HashCObj* self) } PyTypeObject _HashCObjType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey._HashCObj", /*tp_name*/ sizeof(HashCObj), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -87,7 +120,11 @@ PyTypeObject _HashCObjType = { 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ +#if PY_MAJOR_VERSION >= 3 + 0, /*tp_compare*/ +#else (cmpfunc)HashCObj_cmp, /*tp_compare*/ +#endif (reprfunc)HashCObj_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ @@ -100,4 +137,7 @@ PyTypeObject _HashCObjType = { 0, /*tp_as_buffer*/ 0, /*tp_flags*/ "Internal hashing object.", /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + (richcmpfunc)HashCObj_rich_cmp, /*tp_richcompare*/ }; diff --git a/spidermonkey/jsarray.c b/spidermonkey/jsarray.c index ce80615..cbac0b6 100644 --- a/spidermonkey/jsarray.c +++ b/spidermonkey/jsarray.c @@ -116,8 +116,7 @@ static PySequenceMethods Array_seq_methods = { }; PyTypeObject _ArrayType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey.Array", /*tp_name*/ sizeof(Object), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/spidermonkey/jsfunction.c b/spidermonkey/jsfunction.c index 49cd80f..69fbea6 100644 --- a/spidermonkey/jsfunction.c +++ b/spidermonkey/jsfunction.c @@ -136,8 +136,7 @@ static PyMethodDef Function_methods[] = { }; PyTypeObject _FunctionType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey.Function", /*tp_name*/ sizeof(Function), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/spidermonkey/jsiterator.c b/spidermonkey/jsiterator.c index 4c7fe54..69bd5e6 100644 --- a/spidermonkey/jsiterator.c +++ b/spidermonkey/jsiterator.c @@ -130,8 +130,7 @@ static PyMethodDef Iterator_methods[] = { }; PyTypeObject _IteratorType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey.Iterator", /*tp_name*/ sizeof(Iterator), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/spidermonkey/jsobject.c b/spidermonkey/jsobject.c index eea3ed3..be0bbb3 100644 --- a/spidermonkey/jsobject.c +++ b/spidermonkey/jsobject.c @@ -267,6 +267,7 @@ Object_rich_cmp(Object* self, PyObject* other, int op) PyObject* val = NULL; PyObject* otherval = NULL; PyObject* ret = NULL; + PyObject* cmp = NULL; JSContext* cx; JSObject* iter; JSBool status = JS_FALSE; @@ -275,7 +276,6 @@ Object_rich_cmp(Object* self, PyObject* other, int op) jsval pval; int llen; int rlen; - int cmp; JS_BeginRequest(self->cx->cx); @@ -332,10 +332,10 @@ Object_rich_cmp(Object* self, PyObject* other, int op) goto success; } - cmp = PyObject_Compare(val, otherval); - if(PyErr_Occurred()) goto error; + cmp = PyObject_RichCompare(val, otherval, op); + if(cmp == NULL) goto error; - if(cmp != 0) + if(!PyObject_IsTrue(cmp)) { if(op == Py_EQ) ret = Py_False; else ret = Py_True; @@ -386,8 +386,7 @@ PyMappingMethods Object_mapping = { }; PyTypeObject _ObjectType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey.Object", /*tp_name*/ sizeof(Object), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/spidermonkey/libjs/jsdtoa.c b/spidermonkey/libjs/jsdtoa.c index 5b0b09f..0f8089c 100644 --- a/spidermonkey/libjs/jsdtoa.c +++ b/spidermonkey/libjs/jsdtoa.c @@ -50,7 +50,7 @@ #include "jsnum.h" #ifdef JS_THREADSAFE -#include "prlock.h" +#include #endif /**************************************************************** diff --git a/spidermonkey/libjs/jsfile.c b/spidermonkey/libjs/jsfile.c index ed1c4e8..66ef51a 100644 --- a/spidermonkey/libjs/jsfile.c +++ b/spidermonkey/libjs/jsfile.c @@ -88,8 +88,8 @@ #include /* NSPR dependencies */ -#include "prio.h" -#include "prerror.h" +#include +#include #define SPECIAL_FILE_STRING "Special File" #define CURRENTDIR_PROPERTY "currentDir" diff --git a/spidermonkey/libjs/jslock.h b/spidermonkey/libjs/jslock.h index f9ed03d..4b9a5f7 100644 --- a/spidermonkey/libjs/jslock.h +++ b/spidermonkey/libjs/jslock.h @@ -42,10 +42,11 @@ #ifdef JS_THREADSAFE #include "jstypes.h" -#include "pratom.h" -#include "prlock.h" -#include "prcvar.h" -#include "prthread.h" + +#include +#include +#include +#include #include "jsprvtd.h" /* for JSScope, etc. */ #include "jspubtd.h" /* for JSRuntime, etc. */ diff --git a/spidermonkey/pyobject.c b/spidermonkey/pyobject.c index b0b9572..0bcec73 100644 --- a/spidermonkey/pyobject.c +++ b/spidermonkey/pyobject.c @@ -106,12 +106,12 @@ js_get_prop(JSContext* jscx, JSObject* jsobj, jsval key, jsval* val) if(Context_has_access(pycx, jscx, pyobj, pykey) <= 0) goto done; // Yeah. It's ugly as sin. - if(PyString_Check(pykey) || PyUnicode_Check(pykey)) + if(PyBytes_Check(pykey) || PyUnicode_Check(pykey)) { utf8 = PyUnicode_AsUTF8String(pykey); if(utf8 == NULL) goto done; - data = PyString_AsString(utf8); + data = PyBytes_AsString(utf8); if(data == NULL) goto done; if(strcmp("__iterator__", data) == 0) @@ -281,7 +281,7 @@ js_call(JSContext* jscx, JSObject* jsobj, uintN argc, jsval* argv, jsval* rval) } // Use '__call__' as a notice that we want to execute a function. - attrcheck = PyString_FromString("__call__"); + attrcheck = PyBytes_FromString("__call__"); if(attrcheck == NULL) goto error; if(Context_has_access(pycx, jscx, pyobj, attrcheck) <= 0) goto error; @@ -350,7 +350,7 @@ js_ctor(JSContext* jscx, JSObject* jsobj, uintN argc, jsval* argv, jsval* rval) } // Use '__init__' to signal use as a constructor. - attrcheck = PyString_FromString("__init__"); + attrcheck = PyBytes_FromString("__init__"); if(attrcheck == NULL) goto error; if(Context_has_access(pycx, jscx, pyobj, attrcheck) <= 0) goto error; @@ -391,7 +391,7 @@ create_class(Context* cx, PyObject* pyobj) char* classname = NULL; int flags = JSCLASS_HAS_RESERVED_SLOTS(1); - curr = Context_get_class(cx, pyobj->ob_type->tp_name); + curr = Context_get_class(cx, Py_TYPE(pyobj)->tp_name); if(curr != NULL) return (JSClass*) HashCObj_AsVoidPtr(curr); jsclass = (JSClass*) malloc(sizeof(JSClass)); @@ -401,14 +401,14 @@ create_class(Context* cx, PyObject* pyobj) goto error; } - classname = (char*) malloc(strlen(pyobj->ob_type->tp_name)*sizeof(char)); + classname = (char*) malloc(strlen(Py_TYPE(pyobj)->tp_name)*sizeof(char)); if(classname == NULL) { PyErr_NoMemory(); goto error; } - strcpy((char*) classname, pyobj->ob_type->tp_name); + strcpy((char*) classname, Py_TYPE(pyobj)->tp_name); jsclass->name = classname; jsclass->flags = flags; @@ -431,7 +431,7 @@ create_class(Context* cx, PyObject* pyobj) curr = HashCObj_FromVoidPtr(jsclass); if(curr == NULL) goto error; - if(Context_add_class(cx, pyobj->ob_type->tp_name, curr) < 0) goto error; + if(Context_add_class(cx, Py_TYPE(pyobj)->tp_name, curr) < 0) goto error; ret = jsclass; goto success; diff --git a/spidermonkey/runtime.c b/spidermonkey/runtime.c index 233bc8b..92b0c45 100644 --- a/spidermonkey/runtime.c +++ b/spidermonkey/runtime.c @@ -98,8 +98,7 @@ static PyMethodDef Runtime_methods[] = { }; PyTypeObject _RuntimeType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "spidermonkey.Runtime", /*tp_name*/ sizeof(Runtime), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/spidermonkey/spidermonkey.c b/spidermonkey/spidermonkey.c index 48d2dc0..9d4b999 100644 --- a/spidermonkey/spidermonkey.c +++ b/spidermonkey/spidermonkey.c @@ -22,35 +22,93 @@ PyTypeObject* IteratorType = NULL; PyTypeObject* HashCObjType = NULL; PyObject* JSError = NULL; +struct module_state { + PyObject *error; +}; + +#if PY_MAJOR_VERSION >= 3 +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) +#else +#define GETSTATE(m) (&_state) +static struct module_state _state; +#endif + static PyMethodDef spidermonkey_methods[] = { {NULL} }; + +#if PY_MAJOR_VERSION >= 3 + +static int spidermonkey_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +static int spidermonkey_clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "spidermonkey", + "The Python-Spidermonkey bridge.", + sizeof(struct module_state), + spidermonkey_methods, + NULL, + spidermonkey_traverse, + spidermonkey_clear, + NULL +}; + +#define INITERROR return NULL + +PyMODINIT_FUNC +PyInit_spidermonkey(void) + +#else // PY_MAJOR_VERSION == 2 +#define INITERROR return + PyMODINIT_FUNC initspidermonkey(void) +#endif { PyObject* m; - if(PyType_Ready(&_RuntimeType) < 0) return; - if(PyType_Ready(&_ContextType) < 0) return; - if(PyType_Ready(&_ObjectType) < 0) return; + if(PyType_Ready(&_RuntimeType) < 0) INITERROR; + if(PyType_Ready(&_ContextType) < 0) INITERROR; + if(PyType_Ready(&_ObjectType) < 0) INITERROR; _ArrayType.tp_base = &_ObjectType; - if(PyType_Ready(&_ArrayType) < 0) return; + if(PyType_Ready(&_ArrayType) < 0) INITERROR; _FunctionType.tp_base = &_ObjectType; - if(PyType_Ready(&_FunctionType) < 0) return; + if(PyType_Ready(&_FunctionType) < 0) INITERROR; - if(PyType_Ready(&_IteratorType) < 0) return; + if(PyType_Ready(&_IteratorType) < 0) INITERROR; - if(PyType_Ready(&_HashCObjType) < 0) return; + if(PyType_Ready(&_HashCObjType) < 0) INITERROR; + #if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); + #else + m = Py_InitModule3("spidermonkey", spidermonkey_methods, "The Python-Spidermonkey bridge."); + #endif if(m == NULL) { - return; + INITERROR; + } + + struct module_state *st = GETSTATE(m); + st->error = PyErr_NewException("spidermonkey.Error", NULL, NULL); + if (st->error == NULL) { + Py_DECREF(m); + INITERROR; } RuntimeType = &_RuntimeType; @@ -85,4 +143,8 @@ initspidermonkey(void) PyModule_AddObject(m, "JSError", JSError); SpidermonkeyModule = m; + +#if PY_MAJOR_VERSION >= 3 + return m; +#endif } diff --git a/spidermonkey/spidermonkey.h b/spidermonkey/spidermonkey.h index a1ff5c6..ca0a8ea 100644 --- a/spidermonkey/spidermonkey.h +++ b/spidermonkey/spidermonkey.h @@ -10,6 +10,14 @@ #define SPIDERMONKEY_H #include +#include "bytesobject.h" + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_Check PyLong_Check + #define PyInt_AsLong PyLong_AsLong + #define PyInt_FromLong PyLong_FromLong +#endif + #include "structmember.h" #include diff --git a/spidermonkey/string.c b/spidermonkey/string.c index 5c734a2..b214137 100644 --- a/spidermonkey/string.c +++ b/spidermonkey/string.c @@ -17,7 +17,7 @@ py2js_string_obj(Context* cx, PyObject* str) char* bytes; Py_ssize_t len; - if(PyString_Check(str)) + if(PyBytes_Check(str)) { conv = PyUnicode_FromEncodedObject(str, "utf-8", "replace"); if(conv == NULL) goto error; @@ -31,7 +31,7 @@ py2js_string_obj(Context* cx, PyObject* str) encoded = PyUnicode_AsEncodedString(str, "utf-16", "strict"); if(encoded == NULL) goto error; - if(PyString_AsStringAndSize(encoded, &bytes, &len) < 0) goto error; + if(PyBytes_AsStringAndSize(encoded, &bytes, &len) < 0) goto error; if(len < 2) { PyErr_SetString(PyExc_ValueError, "Failed to find byte-order mark."); diff --git a/tests/t.py b/tests/t.py index 339757c..8579c73 100644 --- a/tests/t.py +++ b/tests/t.py @@ -10,7 +10,7 @@ class test(object): def __call__(self, func): def run(): func(*self.args()) - run.func_name = func.func_name + run.__name__ = func.__name__ return run def args(self, func): raise NotImplementedError() @@ -68,7 +68,7 @@ def hasnot(a, b): def raises(exctype, func, *args, **kwargs): try: func(*args, **kwargs) - except exctype, inst: + except exctype as inst: pass else: func_name = getattr(func, "func_name", "") diff --git a/tests/test-access.py b/tests/test-access.py index f5e7c5b..047ecde 100644 --- a/tests/test-access.py +++ b/tests/test-access.py @@ -86,6 +86,7 @@ def __init__(self): def __call__(self, arg): return arg * 2 def check(obj, name): + name = name.decode() if isinstance(name, bytes) else name return name != "__call__" cx.add_global("PepsiCan", PepsiCan) cx.set_access(check) @@ -103,6 +104,7 @@ def func(): cx.add_global("whee", func) def check(obj, name): + name = name.decode() if isinstance(name, bytes) else name return name in ["__call__", "__init__"] or not name.startswith("_") cx.set_access(check); diff --git a/tests/test-global.py b/tests/test-global.py index 1c0104d..da463b9 100644 --- a/tests/test-global.py +++ b/tests/test-global.py @@ -66,7 +66,7 @@ def test_py_with_global(rt): @t.rt() def test_py_with_invalid_global(rt): - t.raises(TypeError, rt.new_context, "Break!") + t.raises(TypeError, rt.new_context, False) @t.rt() def test_py_get_global(rt): diff --git a/tests/test-iterate.py b/tests/test-iterate.py index 8fa7a4f..9d21308 100644 --- a/tests/test-iterate.py +++ b/tests/test-iterate.py @@ -18,8 +18,8 @@ @t.glbl("data", {"foo": "bar", "baz": "bam"}) def test_iter_py_map(cx, glbl): - t.eq(cx.execute(js_for_script), ["foo", "baz"]) - t.eq(cx.execute(js_for_each_script), ["bar", "bam"]) + t.eq(set(cx.execute(js_for_script)), {"foo", "baz"}) + t.eq(set(cx.execute(js_for_each_script)), {"bar", "bam"}) @t.glbl("data", ["a", 2, "zing!"]) def test_iter_py_array(cx, glbl): diff --git a/tests/test-to-python.py b/tests/test-to-python.py index ac2b514..ad5b52f 100644 --- a/tests/test-to-python.py +++ b/tests/test-to-python.py @@ -3,6 +3,10 @@ # This file is part of the python-spidermonkey package released # under the MIT license. import t +try: + unicode +except NameError: + unicode = str @t.cx() def test_to_py_int(cx):