You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1255 lines
40 KiB
1255 lines
40 KiB
Add support for Python 3.
|
|
Based on patch from ubuntu.
|
|
Modifed to work with Python 2.5 by Mike Gilbert (floppym).
|
|
|
|
Description: Add support for Python 3
|
|
Origin: http://sourceforge.net/tracker/?func=detail&aid=3188495&group_id=28236&atid=392779
|
|
Author: Markus Koetter
|
|
Author: Michael Terry <michael.terry@canonical.com>
|
|
|
|
diff --git a/examples/basicfirst.py b/examples/basicfirst.py
|
|
index 4e49465..6b658fc 100644
|
|
--- a/examples/basicfirst.py
|
|
+++ b/examples/basicfirst.py
|
|
@@ -13,13 +13,17 @@ class Test:
|
|
def body_callback(self, buf):
|
|
self.contents = self.contents + buf
|
|
|
|
-print >>sys.stderr, 'Testing', pycurl.version
|
|
+print('Testing', pycurl.version, file=sys.stderr)
|
|
|
|
-t = Test()
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, 'http://curl.haxx.se/dev/')
|
|
-c.setopt(c.WRITEFUNCTION, t.body_callback)
|
|
-c.perform()
|
|
-c.close()
|
|
+try:
|
|
+ t = Test()
|
|
+ c = pycurl.Curl()
|
|
+ c.setopt(c.URL, sys.argv[1])
|
|
+ c.setopt(c.WRITEFUNCTION, t.body_callback)
|
|
+ c.perform()
|
|
+ c.close()
|
|
+# print(t)
|
|
+ print(t.contents)
|
|
+except Exception as e:
|
|
+ print(e)
|
|
|
|
-print t.contents
|
|
diff --git a/examples/retriever-multi.py b/examples/retriever-multi.py
|
|
index 0b4b417..fbf7515 100644
|
|
--- a/examples/retriever-multi.py
|
|
+++ b/examples/retriever-multi.py
|
|
@@ -10,6 +10,7 @@
|
|
|
|
import sys
|
|
import pycurl
|
|
+import time
|
|
|
|
# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
|
|
# the libcurl tutorial for more info.
|
|
@@ -31,7 +32,7 @@ try:
|
|
if len(sys.argv) >= 3:
|
|
num_conn = int(sys.argv[2])
|
|
except:
|
|
- print "Usage: %s <file with URLs to fetch> [<# of concurrent connections>]" % sys.argv[0]
|
|
+ print("Usage: %s <file with URLs to fetch> [<# of concurrent connections>]" % sys.argv[0])
|
|
raise SystemExit
|
|
|
|
|
|
@@ -50,8 +51,8 @@ assert queue, "no URLs given"
|
|
num_urls = len(queue)
|
|
num_conn = min(num_conn, num_urls)
|
|
assert 1 <= num_conn <= 10000, "invalid number of concurrent connections"
|
|
-print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM)
|
|
-print "----- Getting", num_urls, "URLs using", num_conn, "connections -----"
|
|
+print("PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM))
|
|
+print("----- Getting", num_urls, "URLs using", num_conn, "connections -----")
|
|
|
|
|
|
# Pre-allocate a list of curl objects
|
|
@@ -79,6 +80,9 @@ while num_processed < num_urls:
|
|
c.fp = open(filename, "wb")
|
|
c.setopt(pycurl.URL, url)
|
|
c.setopt(pycurl.WRITEDATA, c.fp)
|
|
+# print(c.fp)
|
|
+# c.fp.close()
|
|
+# c.fp = None
|
|
m.add_handle(c)
|
|
# store some info
|
|
c.filename = filename
|
|
@@ -92,16 +96,17 @@ while num_processed < num_urls:
|
|
while 1:
|
|
num_q, ok_list, err_list = m.info_read()
|
|
for c in ok_list:
|
|
+ c.fp.flush()
|
|
c.fp.close()
|
|
c.fp = None
|
|
m.remove_handle(c)
|
|
- print "Success:", c.filename, c.url, c.getinfo(pycurl.EFFECTIVE_URL)
|
|
+ print("Success:", c.filename, c.url, c.getinfo(pycurl.EFFECTIVE_URL))
|
|
freelist.append(c)
|
|
for c, errno, errmsg in err_list:
|
|
c.fp.close()
|
|
c.fp = None
|
|
m.remove_handle(c)
|
|
- print "Failed: ", c.filename, c.url, errno, errmsg
|
|
+ print("Failed: ", c.filename, c.url, errno, errmsg)
|
|
freelist.append(c)
|
|
num_processed = num_processed + len(ok_list) + len(err_list)
|
|
if num_q == 0:
|
|
@@ -120,3 +125,4 @@ for c in m.handles:
|
|
c.close()
|
|
m.close()
|
|
|
|
+#time.sleep(30)
|
|
diff --git a/python/curl/__init__.py b/python/curl/__init__.py
|
|
index b002618..22762c4 100644
|
|
--- a/python/curl/__init__.py
|
|
+++ b/python/curl/__init__.py
|
|
@@ -6,11 +6,11 @@
|
|
#
|
|
# By Eric S. Raymond, April 2003.
|
|
|
|
-import os, sys, urllib, exceptions, mimetools, pycurl
|
|
+import os, sys, pycurl
|
|
try:
|
|
- from cStringIO import StringIO
|
|
+ from urllib.parse import urlencode
|
|
except ImportError:
|
|
- from StringIO import StringIO
|
|
+ from urllib import urlencode
|
|
|
|
try:
|
|
import signal
|
|
@@ -63,7 +63,7 @@ class Curl:
|
|
|
|
def set_option(self, *args):
|
|
"Set an option on the retrieval."
|
|
- apply(self.handle.setopt, args)
|
|
+ self.handle.setopt(*args)
|
|
|
|
def set_verbosity(self, level):
|
|
"Set verbosity to 1 to see transactions."
|
|
@@ -83,14 +83,14 @@ class Curl:
|
|
def get(self, url="", params=None):
|
|
"Ship a GET request for a specified URL, capture the response."
|
|
if params:
|
|
- url += "?" + urllib.urlencode(params)
|
|
+ url += "?" + urlencode(params)
|
|
self.set_option(pycurl.HTTPGET, 1)
|
|
return self.__request(url)
|
|
|
|
def post(self, cgi, params):
|
|
"Ship a POST request to a specified CGI, capture the response."
|
|
self.set_option(pycurl.POST, 1)
|
|
- self.set_option(pycurl.POSTFIELDS, urllib.urlencode(params))
|
|
+ self.set_option(pycurl.POSTFIELDS, urlencode(params))
|
|
return self.__request(cgi)
|
|
|
|
def body(self):
|
|
@@ -103,7 +103,7 @@ class Curl:
|
|
|
|
def get_info(self, *args):
|
|
"Get information about retrieval."
|
|
- return apply(self.handle.getinfo, args)
|
|
+ return self.handle.getinfo(*args)
|
|
|
|
def info(self):
|
|
"Return a dictionary with all info on the last response."
|
|
@@ -164,10 +164,10 @@ if __name__ == "__main__":
|
|
url = sys.argv[1]
|
|
c = Curl()
|
|
c.get(url)
|
|
- print c.body()
|
|
- print '='*74 + '\n'
|
|
+ print(c.body())
|
|
+ print('='*74 + '\n')
|
|
import pprint
|
|
pprint.pprint(c.info())
|
|
- print c.get_info(pycurl.OS_ERRNO)
|
|
- print c.info()['os-errno']
|
|
+ print(c.get_info(pycurl.OS_ERRNO))
|
|
+ print(c.info()['os-errno'])
|
|
c.close()
|
|
diff --git a/setup.py b/setup.py
|
|
index 172f280..1e6b21f 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -31,7 +31,7 @@ def scan_argv(s, default):
|
|
i = 1
|
|
while i < len(sys.argv):
|
|
arg = sys.argv[i]
|
|
- if string.find(arg, s) == 0:
|
|
+ if str.find(arg, s) == 0:
|
|
p = arg[len(s):]
|
|
assert p, arg
|
|
del sys.argv[i]
|
|
@@ -46,8 +46,8 @@ def add_libdirs(envvar, sep, fatal=0):
|
|
v = os.environ.get(envvar)
|
|
if not v:
|
|
return
|
|
- for dir in string.split(v, sep):
|
|
- dir = string.strip(dir)
|
|
+ for dir in str.split(v, sep):
|
|
+ dir = str.strip(dir)
|
|
if not dir:
|
|
continue
|
|
dir = os.path.normpath(dir)
|
|
@@ -55,7 +55,7 @@ def add_libdirs(envvar, sep, fatal=0):
|
|
if not dir in library_dirs:
|
|
library_dirs.append(dir)
|
|
elif fatal:
|
|
- print "FATAL: bad directory %s in environment variable %s" % (dir, envvar)
|
|
+ print("FATAL: bad directory %s in environment variable %s" % (dir, envvar))
|
|
sys.exit(1)
|
|
|
|
|
|
@@ -65,13 +65,13 @@ if sys.platform == "win32":
|
|
# and thus unlikely to match your installation.
|
|
CURL_DIR = r"c:\src\build\pycurl\curl-7.16.2.1"
|
|
CURL_DIR = scan_argv("--curl-dir=", CURL_DIR)
|
|
- print "Using curl directory:", CURL_DIR
|
|
+ print("Using curl directory:", CURL_DIR)
|
|
assert os.path.isdir(CURL_DIR), "please check CURL_DIR in setup.py"
|
|
include_dirs.append(os.path.join(CURL_DIR, "include"))
|
|
extra_objects.append(os.path.join(CURL_DIR, "lib", "libcurl.lib"))
|
|
extra_link_args.extend(["gdi32.lib", "wldap32.lib", "winmm.lib", "ws2_32.lib",])
|
|
add_libdirs("LIB", ";")
|
|
- if string.find(sys.version, "MSC") >= 0:
|
|
+ if str.find(sys.version, "MSC") >= 0:
|
|
extra_compile_args.append("-O2")
|
|
extra_compile_args.append("-GF") # enable read-only string pooling
|
|
extra_compile_args.append("-WX") # treat warnings as errors
|
|
@@ -85,10 +85,10 @@ else:
|
|
CURL_CONFIG = scan_argv("--curl-config=", CURL_CONFIG)
|
|
d = os.popen("'%s' --version" % CURL_CONFIG).read()
|
|
if d:
|
|
- d = string.strip(d)
|
|
+ d = str.strip(d)
|
|
if not d:
|
|
- raise Exception, ("`%s' not found -- please install the libcurl development files" % CURL_CONFIG)
|
|
- print "Using %s (%s)" % (CURL_CONFIG, d)
|
|
+ raise Exception("`%s' not found -- please install the libcurl development files" % CURL_CONFIG)
|
|
+ print("Using %s (%s)" % (CURL_CONFIG, d))
|
|
for e in split_quoted(os.popen("'%s' --cflags" % CURL_CONFIG).read()):
|
|
if e[:2] == "-I":
|
|
# do not add /usr/include
|
|
@@ -209,4 +209,4 @@ if __name__ == "__main__":
|
|
for o in ext.extra_objects:
|
|
assert os.path.isfile(o), o
|
|
# We can live with the deprecationwarning for a while
|
|
- apply(setup, (), setup_args)
|
|
+ setup(*(), **setup_args)
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 8b7245d..dc9a90c 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -97,6 +97,17 @@ static void pycurl_ssl_init(void);
|
|
static void pycurl_ssl_cleanup(void);
|
|
#endif
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ #define PyInt_Type PyLong_Type
|
|
+ #define PyInt_Check(op) PyLong_Check(op)
|
|
+ #define PyInt_FromLong PyLong_FromLong
|
|
+ #define PyInt_AsLong PyLong_AsLong
|
|
+#endif
|
|
+
|
|
+#ifndef Py_TYPE
|
|
+ #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
|
|
+#endif
|
|
+
|
|
/* Calculate the number of OBJECTPOINT options we need to store */
|
|
#define OPTIONS_SIZE ((int)CURLOPT_LASTENTRY % 10000)
|
|
#define MOPTIONS_SIZE ((int)CURLMOPT_LASTENTRY % 10000)
|
|
@@ -161,6 +172,7 @@ typedef struct {
|
|
PyObject *opensocket_cb;
|
|
/* file objects */
|
|
PyObject *readdata_fp;
|
|
+ PyObject *writedata;
|
|
PyObject *writedata_fp;
|
|
PyObject *writeheader_fp;
|
|
/* misc */
|
|
@@ -202,16 +214,50 @@ typedef struct {
|
|
# define PY_LONG_LONG LONG_LONG
|
|
#endif
|
|
|
|
+int PyUnicode_AsStringAndSize(PyObject *obj, char **buffer, Py_ssize_t *length)
|
|
+{
|
|
+ Py_ssize_t pysize = PyUnicode_GetSize(obj);
|
|
+ wchar_t * str = (wchar_t *) malloc((pysize + 1) * sizeof(wchar_t));
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ PyUnicode_AsWideChar(obj, str, pysize);
|
|
+#else
|
|
+ PyUnicode_AsWideChar((PyUnicodeObject *) obj, str, pysize);
|
|
+#endif
|
|
+ str[pysize] = '\0';
|
|
+
|
|
+// measure size
|
|
+ size_t csize = wcstombs(0, str, 0);
|
|
+ if( csize == (size_t) -1 )
|
|
+ {
|
|
+ free(str);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ char *cstr = (char *) malloc(csize + 1);
|
|
+
|
|
+// convert
|
|
+ wcstombs(cstr, str, csize + 1);
|
|
+ *buffer = cstr;
|
|
+ if( length )
|
|
+ *length = csize;
|
|
+ free(str);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
/* Like PyString_AsString(), but set an exception if the string contains
|
|
* embedded NULs. Actually PyString_AsStringAndSize() already does that for
|
|
* us if the `len' parameter is NULL - see Objects/stringobject.c.
|
|
*/
|
|
-
|
|
static char *PyString_AsString_NoNUL(PyObject *obj)
|
|
{
|
|
char *s = NULL;
|
|
Py_ssize_t r;
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ r = PyUnicode_AsStringAndSize(obj, &s, NULL);
|
|
+#else
|
|
r = PyString_AsStringAndSize(obj, &s, NULL);
|
|
+#endif
|
|
if (r != 0)
|
|
return NULL; /* exception already set */
|
|
assert(s != NULL);
|
|
@@ -236,7 +282,11 @@ static PyObject *convert_slist(struct curl_slist *slist, int free_flags)
|
|
if (slist->data == NULL) {
|
|
v = Py_None; Py_INCREF(v);
|
|
} else {
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ v = PyUnicode_FromString(slist->data);
|
|
+#else
|
|
v = PyString_FromString(slist->data);
|
|
+#endif
|
|
}
|
|
if (v == NULL || PyList_Append(ret, v) != 0) {
|
|
Py_XDECREF(v);
|
|
@@ -272,7 +322,7 @@ get_thread_state(const CurlObject *self)
|
|
*/
|
|
if (self == NULL)
|
|
return NULL;
|
|
- assert(self->ob_type == p_Curl_Type);
|
|
+ assert(Py_TYPE(self) == p_Curl_Type);
|
|
if (self->state != NULL)
|
|
{
|
|
/* inside perform() */
|
|
@@ -302,7 +352,7 @@ get_thread_state_multi(const CurlMultiObject *self)
|
|
*/
|
|
if (self == NULL)
|
|
return NULL;
|
|
- assert(self->ob_type == p_CurlMulti_Type);
|
|
+ assert(Py_TYPE(self) == p_CurlMulti_Type);
|
|
if (self->state != NULL)
|
|
{
|
|
/* inside multi_perform() */
|
|
@@ -318,7 +368,7 @@ static void
|
|
assert_share_state(const CurlShareObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
- assert(self->ob_type == p_CurlShare_Type);
|
|
+ assert(Py_TYPE(self) == p_CurlShare_Type);
|
|
assert(self->lock != NULL);
|
|
}
|
|
|
|
@@ -328,7 +378,7 @@ static void
|
|
assert_curl_state(const CurlObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
- assert(self->ob_type == p_Curl_Type);
|
|
+ assert(Py_TYPE(self) == p_Curl_Type);
|
|
(void) get_thread_state(self);
|
|
}
|
|
|
|
@@ -338,7 +388,7 @@ static void
|
|
assert_multi_state(const CurlMultiObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
- assert(self->ob_type == p_CurlMulti_Type);
|
|
+ assert(Py_TYPE(self) == p_CurlMulti_Type);
|
|
if (self->state != NULL) {
|
|
assert(self->multi_handle != NULL);
|
|
}
|
|
@@ -676,7 +726,8 @@ do_curlshare_setopt(CurlShareObject *self, PyObject *args)
|
|
|
|
/* Handle the case of integer arguments */
|
|
if (PyInt_Check(obj)) {
|
|
- long d = PyInt_AsLong(obj);
|
|
+ long d = PyLong_AsLong(obj);
|
|
+
|
|
if (d != CURL_LOCK_DATA_COOKIE && d != CURL_LOCK_DATA_DNS) {
|
|
goto error;
|
|
}
|
|
@@ -750,6 +801,7 @@ util_curl_new(void)
|
|
return self;
|
|
}
|
|
|
|
+size_t default_write_callback(char *ptr, size_t size, size_t nmemb, void *stream);
|
|
|
|
/* constructor - this is a module-level function returning a new instance */
|
|
static CurlObject *
|
|
@@ -809,11 +861,22 @@ do_curl_new(PyObject *dummy)
|
|
}
|
|
self->options[ OPT_INDEX(CURLOPT_USERAGENT) ] = s; s = NULL;
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ res = curl_easy_setopt(self->handle, CURLOPT_WRITEFUNCTION, default_write_callback);
|
|
+ if (res != CURLE_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+ res = curl_easy_setopt(self->handle, CURLOPT_WRITEDATA, self);
|
|
+ if (res != CURLE_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Success - return new object */
|
|
return self;
|
|
|
|
error:
|
|
- Py_DECREF(self); /* this also closes self->handle */
|
|
+ Py_XDECREF(self); /* this also closes self->handle */
|
|
PyErr_SetString(ErrorObject, "initializing curl failed");
|
|
return NULL;
|
|
}
|
|
@@ -880,7 +943,7 @@ util_curl_close(CurlObject *self)
|
|
/* Zero handle and thread-state to disallow any operations to be run
|
|
* from now on */
|
|
assert(self != NULL);
|
|
- assert(self->ob_type == p_Curl_Type);
|
|
+ assert(Py_TYPE(self) == p_Curl_Type);
|
|
handle = self->handle;
|
|
self->handle = NULL;
|
|
if (handle == NULL) {
|
|
@@ -965,7 +1028,12 @@ do_curl_errstr(CurlObject *self)
|
|
return NULL;
|
|
}
|
|
self->error[sizeof(self->error) - 1] = 0;
|
|
+
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ return PyUnicode_FromString(self->error);
|
|
+#else
|
|
return PyString_FromString(self->error);
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -1125,6 +1193,52 @@ write_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
return util_write_callback(0, ptr, size, nmemb, stream);
|
|
}
|
|
|
|
+
|
|
+size_t
|
|
+default_write_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
+{
|
|
+ CurlObject *obj = (CurlObject *)stream;
|
|
+ PyThreadState *tmp_state;
|
|
+ CurlObject *self = (CurlObject *)stream;
|
|
+
|
|
+ /* acquire thread */
|
|
+ int ret = 0;
|
|
+ tmp_state = get_thread_state(self);
|
|
+ if (tmp_state == NULL)
|
|
+ return ret;
|
|
+ PyEval_AcquireThread(tmp_state);
|
|
+
|
|
+ if(obj->writedata_fp != NULL)
|
|
+ {
|
|
+ /**
|
|
+ * I'd prefer this code, but
|
|
+ * PyFile_WriteObject converts the object to str or repr, which are of type str
|
|
+ * and the write() fn expects bytes or buffer ...
|
|
+ */
|
|
+/*
|
|
+ PyObject *w = PyBytes_FromStringAndSize(ptr, size*nmemb);
|
|
+ printf("writedata_fp %p w %p s %i\n", obj->writedata_fp, w, PyBytes_GET_SIZE(w));
|
|
+ Py_INCREF(w);
|
|
+ if( PyFile_WriteObject(w, obj->writedata_fp, Py_PRINT_RAW) != 0 )
|
|
+ {
|
|
+ PyErr_Print();
|
|
+ ret = -1;
|
|
+ }
|
|
+
|
|
+ Py_DECREF(w);
|
|
+*/
|
|
+ int fd = PyObject_AsFileDescriptor(((CurlObject *)stream)->writedata_fp);
|
|
+ ret = write(fd, ptr, size*nmemb);
|
|
+ }else
|
|
+ {
|
|
+ fwrite(ptr, size, nmemb, stdout);
|
|
+ }
|
|
+
|
|
+ PyEval_ReleaseThread(tmp_state);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
static size_t
|
|
header_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
{
|
|
@@ -1166,6 +1280,7 @@ opensocket_callback(void *clientp, curlsocktype purpose,
|
|
ret = CURL_SOCKET_BAD;
|
|
goto verbose_error;
|
|
}
|
|
+
|
|
// normal operation:
|
|
if (PyInt_Check(fileno_result)) {
|
|
ret = dup(PyInt_AsLong(fileno_result));
|
|
@@ -1227,11 +1342,19 @@ read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
goto verbose_error;
|
|
|
|
/* handle result */
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (PyBytes_Check(result)) {
|
|
+#else
|
|
if (PyString_Check(result)) {
|
|
+#endif
|
|
char *buf = NULL;
|
|
Py_ssize_t obj_size = -1;
|
|
Py_ssize_t r;
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ r = PyBytes_AsStringAndSize(result, &buf, &obj_size);
|
|
+#else
|
|
r = PyString_AsStringAndSize(result, &buf, &obj_size);
|
|
+#endif
|
|
if (r != 0 || obj_size < 0 || obj_size > total_size) {
|
|
PyErr_Format(ErrorObject, "invalid return value for read callback %ld %ld", (long)obj_size, (long)total_size);
|
|
goto verbose_error;
|
|
@@ -1404,6 +1527,7 @@ ioctl_callback(CURL *curlobj, int cmd, void *stream)
|
|
if (result == Py_None) {
|
|
ret = CURLIOE_OK; /* None means success */
|
|
}
|
|
+
|
|
else if (PyInt_Check(result)) {
|
|
ret = (int) PyInt_AsLong(result);
|
|
if (ret >= CURLIOE_LAST || ret < 0) {
|
|
@@ -1587,7 +1711,11 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
#endif
|
|
|
|
/* Handle the case of string arguments */
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (PyUnicode_Check(obj)) {
|
|
+#else
|
|
if (PyString_Check(obj)) {
|
|
+#endif
|
|
char *str = NULL;
|
|
Py_ssize_t len = -1;
|
|
char *buf;
|
|
@@ -1636,8 +1764,13 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
return NULL;
|
|
break;
|
|
case CURLOPT_POSTFIELDS:
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (PyUnicode_AsStringAndSize(obj, &str, &len) != 0)
|
|
+ return NULL;
|
|
+#else
|
|
if (PyString_AsStringAndSize(obj, &str, &len) != 0)
|
|
return NULL;
|
|
+#endif
|
|
/* automatically set POSTFIELDSIZE */
|
|
if (len <= INT_MAX) {
|
|
res = curl_easy_setopt(self->handle, CURLOPT_POSTFIELDSIZE, (long)len);
|
|
@@ -1686,7 +1819,6 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
/* Handle the case of integer arguments */
|
|
if (PyInt_Check(obj)) {
|
|
long d = PyInt_AsLong(obj);
|
|
-
|
|
if (IS_LONG_OPTION(option))
|
|
res = curl_easy_setopt(self->handle, (CURLoption)option, (long)d);
|
|
else if (IS_OFF_T_OPTION(option))
|
|
@@ -1727,8 +1859,12 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
#undef IS_OFF_T_OPTION
|
|
|
|
/* Handle the case of file objects */
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ extern PyTypeObject PyIOBase_Type;
|
|
+ if(PyObject_IsInstance(obj, (PyObject *)&PyIOBase_Type) == 1) {
|
|
+#else
|
|
if (PyFile_Check(obj)) {
|
|
- FILE *fp;
|
|
+#endif
|
|
|
|
/* Ensure the option specified a file as well as the input */
|
|
switch (option) {
|
|
@@ -1745,7 +1881,13 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
PyErr_SetString(PyExc_TypeError, "files are not supported for this option");
|
|
return NULL;
|
|
}
|
|
-
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+// printf("WRITEDATA %p\n",obj);
|
|
+// int fd = PyObject_AsFileDescriptor(obj);
|
|
+// printf("fd is %i\n", fd);
|
|
+// fp = fdopen(fd, "w");
|
|
+#else
|
|
+ FILE *fp;
|
|
fp = PyFile_AsFile(obj);
|
|
if (fp == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "second argument must be open file");
|
|
@@ -1755,6 +1897,7 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
if (res != CURLE_OK) {
|
|
CURLERROR_RETVAL();
|
|
}
|
|
+#endif
|
|
Py_INCREF(obj);
|
|
|
|
switch (option) {
|
|
@@ -1844,14 +1987,27 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
PyErr_SetString(PyExc_TypeError, "tuple must contain two elements (name, value)");
|
|
return NULL;
|
|
}
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(listitem, 0), &nstr, &nlen) != 0) {
|
|
+#else
|
|
if (PyString_AsStringAndSize(PyTuple_GET_ITEM(listitem, 0), &nstr, &nlen) != 0) {
|
|
+#endif
|
|
curl_formfree(post);
|
|
PyErr_SetString(PyExc_TypeError, "tuple must contain string as first element");
|
|
return NULL;
|
|
}
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (PyUnicode_Check(PyTuple_GET_ITEM(listitem, 1))) {
|
|
+#else
|
|
if (PyString_Check(PyTuple_GET_ITEM(listitem, 1))) {
|
|
+#endif
|
|
/* Handle strings as second argument for backwards compatibility */
|
|
+
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(listitem, 1), &cstr, &clen);
|
|
+#else
|
|
PyString_AsStringAndSize(PyTuple_GET_ITEM(listitem, 1), &cstr, &clen);
|
|
+#endif
|
|
/* INFO: curl_formadd() internally does memdup() the data, so
|
|
* embedded NUL characters _are_ allowed here. */
|
|
res = curl_formadd(&post, &last,
|
|
@@ -1905,7 +2061,11 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
curl_formfree(post);
|
|
return NULL;
|
|
}
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (!PyUnicode_Check(PyTuple_GET_ITEM(t, j+1))) {
|
|
+#else
|
|
if (!PyString_Check(PyTuple_GET_ITEM(t, j+1))) {
|
|
+#endif
|
|
PyErr_SetString(PyExc_TypeError, "value must be string");
|
|
PyMem_Free(forms);
|
|
curl_formfree(post);
|
|
@@ -1923,7 +2083,11 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
curl_formfree(post);
|
|
return NULL;
|
|
}
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(t, j+1), &ostr, &olen);
|
|
+#else
|
|
PyString_AsStringAndSize(PyTuple_GET_ITEM(t, j+1), &ostr, &olen);
|
|
+#endif
|
|
forms[k].option = val;
|
|
forms[k].value = ostr;
|
|
++k;
|
|
@@ -1975,7 +2139,11 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
struct curl_slist *nlist;
|
|
char *str;
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (!PyUnicode_Check(listitem)) {
|
|
+#else
|
|
if (!PyString_Check(listitem)) {
|
|
+#endif
|
|
curl_slist_free_all(slist);
|
|
PyErr_SetString(PyExc_TypeError, "list items must be string objects");
|
|
return NULL;
|
|
@@ -2190,7 +2358,12 @@ do_curl_getinfo(CurlObject *self, PyObject *args)
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ return PyUnicode_FromString(s_res);
|
|
+#else
|
|
return PyString_FromString(s_res);
|
|
+#endif
|
|
+
|
|
}
|
|
|
|
case CURLINFO_CONNECT_TIME:
|
|
@@ -2849,7 +3022,7 @@ do_multi_info_read(CurlMultiObject *self, PyObject *args)
|
|
Py_DECREF(ok_list);
|
|
CURLERROR_MSG("Unable to fetch curl handle from curl object");
|
|
}
|
|
- assert(co->ob_type == p_Curl_Type);
|
|
+ assert(Py_TYPE(co) == p_Curl_Type);
|
|
if (msg->msg != CURLMSG_DONE) {
|
|
/* FIXME: what does this mean ??? */
|
|
}
|
|
@@ -2930,7 +3103,6 @@ do_multi_select(CurlMultiObject *self, PyObject *args)
|
|
* socket code to report any errors.
|
|
*/
|
|
}
|
|
-
|
|
return PyInt_FromLong(n);
|
|
}
|
|
|
|
@@ -2995,6 +3167,116 @@ static PyObject *curlobject_constants = NULL;
|
|
static PyObject *curlmultiobject_constants = NULL;
|
|
static PyObject *curlshareobject_constants = NULL;
|
|
|
|
+
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+static PyObject *
|
|
+my_getattro(PyObject *co, PyObject *name, PyObject *dict1, PyObject *dict2, PyMethodDef *m)
|
|
+{
|
|
+ PyObject *v = NULL;
|
|
+ if( v == NULL && dict1 != NULL )
|
|
+ v = PyDict_GetItem(dict1, name);
|
|
+ if( v == NULL && dict2 != NULL )
|
|
+ v = PyDict_GetItem(dict2, name);
|
|
+ if( v != NULL )
|
|
+ {
|
|
+ Py_INCREF(v);
|
|
+ return v;
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int
|
|
+my_setattro(PyObject **dict, PyObject *name, PyObject *v)
|
|
+{
|
|
+ if( *dict == NULL )
|
|
+ {
|
|
+ *dict = PyDict_New();
|
|
+ if( *dict == NULL )
|
|
+ return -1;
|
|
+ }
|
|
+ return PyDict_SetItem(*dict, name, v);
|
|
+}
|
|
+
|
|
+PyObject *do_curl_getattro(PyObject *o, PyObject *n)
|
|
+{
|
|
+ PyObject *v = PyObject_GenericGetAttr(o, n);
|
|
+ if( !v && PyErr_ExceptionMatches(PyExc_AttributeError) )
|
|
+ {
|
|
+ PyErr_Clear();
|
|
+ v = my_getattro(o, n, ((CurlObject *)o)->dict,
|
|
+ curlobject_constants, curlobject_methods);
|
|
+ }
|
|
+ return v;
|
|
+}
|
|
+
|
|
+static int
|
|
+do_curl_setattro(PyObject *o, PyObject *name, PyObject *v)
|
|
+{
|
|
+ assert_curl_state((CurlObject *)o);
|
|
+ if( v )
|
|
+ {
|
|
+ return my_setattro(&((CurlObject *)o)->dict, name, v);
|
|
+ } else
|
|
+ {
|
|
+ return PyObject_GenericSetAttr(o, name, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+static PyObject *
|
|
+do_multi_getattro(PyObject *o, PyObject *n)
|
|
+{
|
|
+ assert_multi_state((CurlMultiObject *)o);
|
|
+ PyObject *v = PyObject_GenericGetAttr(o, n);
|
|
+ if( !v && PyErr_ExceptionMatches(PyExc_AttributeError) )
|
|
+ {
|
|
+ PyErr_Clear();
|
|
+ v = my_getattro(o, n, ((CurlMultiObject *)o)->dict,
|
|
+ curlmultiobject_constants, curlmultiobject_methods);
|
|
+ }
|
|
+ return v;
|
|
+}
|
|
+
|
|
+static int
|
|
+do_multi_setattro(PyObject *o, PyObject *n, PyObject *v)
|
|
+{
|
|
+ assert_multi_state((CurlMultiObject *)o);
|
|
+ if( v )
|
|
+ {
|
|
+ return my_setattro(&((CurlMultiObject *)o)->dict, n, v);
|
|
+ } else
|
|
+ {
|
|
+ return PyObject_GenericSetAttr(o, n, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+static PyObject *
|
|
+do_share_getattro(PyObject *o, PyObject *n)
|
|
+{
|
|
+ assert_share_state((CurlShareObject *)o);
|
|
+ PyObject *v = PyObject_GenericGetAttr(o, n);
|
|
+ if( !v && PyErr_ExceptionMatches(PyExc_AttributeError) )
|
|
+ {
|
|
+ PyErr_Clear();
|
|
+ v = my_getattro(o, n, ((CurlShareObject *)o)->dict,
|
|
+ curlshareobject_constants, curlshareobject_methods);
|
|
+ }
|
|
+ return v;
|
|
+}
|
|
+
|
|
+static int
|
|
+do_share_setattro(PyObject *o, PyObject *n, PyObject *v)
|
|
+{
|
|
+ assert_share_state((CurlShareObject *)o);
|
|
+ if( v )
|
|
+ {
|
|
+ return my_setattro(&((CurlShareObject *)o)->dict, n, v);
|
|
+ } else
|
|
+ {
|
|
+ return PyObject_GenericSetAttr(o, n, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+#else
|
|
static int
|
|
my_setattr(PyObject **dict, char *name, PyObject *v)
|
|
{
|
|
@@ -3029,6 +3311,7 @@ my_getattr(PyObject *co, char *name, PyObject *dict1, PyObject *dict2, PyMethodD
|
|
return Py_FindMethod(m, co, name);
|
|
}
|
|
|
|
+
|
|
static int
|
|
do_share_setattr(CurlShareObject *so, char *name, PyObject *v)
|
|
{
|
|
@@ -3073,10 +3356,53 @@ do_multi_getattr(CurlMultiObject *co, char *name)
|
|
return my_getattr((PyObject *)co, name, co->dict,
|
|
curlmultiobject_constants, curlmultiobject_methods);
|
|
}
|
|
+#endif
|
|
|
|
|
|
-/* --------------- actual type definitions --------------- */
|
|
|
|
+/* --------------- actual type definitions --------------- */
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+static PyTypeObject CurlShare_Type = {
|
|
+ PyVarObject_HEAD_INIT(NULL, 0)
|
|
+ "pycurl.CurlShare", /* tp_name */
|
|
+ sizeof(CurlShareObject), /* tp_basicsize */
|
|
+ 0, /* tp_itemsize */
|
|
+ (destructor)do_share_dealloc,/* tp_dealloc */
|
|
+ 0, /* tp_print */
|
|
+ 0, /* tp_getattr */
|
|
+ 0, /* tp_setattr */
|
|
+ 0, /* tp_reserved */
|
|
+ 0, /* tp_repr */
|
|
+ 0, /* tp_as_number */
|
|
+ 0, /* tp_as_sequence */
|
|
+ 0, /* tp_as_mapping */
|
|
+ 0, /* tp_hash */
|
|
+ 0, /* tp_call */
|
|
+ 0, /* tp_str */
|
|
+ (getattrofunc)do_share_getattro, /* tp_getattro */
|
|
+ (setattrofunc)do_share_setattro, /* tp_setattro */
|
|
+ 0, /* tp_as_buffer */
|
|
+ Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
+ 0, /* tp_doc */
|
|
+ (traverseproc)do_share_traverse, /* tp_traverse */
|
|
+ (inquiry)do_share_clear, /* tp_clear */
|
|
+ 0, /* tp_richcompare */
|
|
+ 0, /* tp_weaklistoffset */
|
|
+ 0, /* tp_iter */
|
|
+ 0, /* tp_iternext */
|
|
+ curlshareobject_methods, /* tp_methods */
|
|
+ 0, /* tp_members */
|
|
+ 0, /* tp_getset */
|
|
+ 0, /* tp_base */
|
|
+ 0, /* tp_dict */
|
|
+ 0, /* tp_descr_get */
|
|
+ 0, /* tp_descr_set */
|
|
+ 0, /* tp_dictoffset */
|
|
+ 0, /* tp_init */
|
|
+ 0, /* tp_alloc */
|
|
+ 0, /* tp_new */
|
|
+};
|
|
+#else
|
|
static PyTypeObject CurlShare_Type = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
@@ -3107,7 +3433,50 @@ static PyTypeObject CurlShare_Type = {
|
|
* safely ignore any compiler warnings about missing initializers.
|
|
*/
|
|
};
|
|
+#endif
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+static PyTypeObject Curl_Type = {
|
|
+ PyVarObject_HEAD_INIT(NULL, 0)
|
|
+ "pycurl.Curl", /* tp_name */
|
|
+ sizeof(CurlObject), /* tp_basicsize */
|
|
+ 0, /* tp_itemsize */
|
|
+ (destructor)do_curl_dealloc,/* tp_dealloc */
|
|
+ 0, /* tp_print */
|
|
+ 0, /* tp_getattr */
|
|
+ 0, /* tp_setattr */
|
|
+ 0, /* tp_reserved */
|
|
+ 0, /* tp_repr */
|
|
+ 0, /* tp_as_number */
|
|
+ 0, /* tp_as_sequence */
|
|
+ 0, /* tp_as_mapping */
|
|
+ 0, /* tp_hash */
|
|
+ 0, /* tp_call */
|
|
+ 0, /* tp_str */
|
|
+ (getattrofunc)do_curl_getattro, /* tp_getattro */
|
|
+ (setattrofunc)do_curl_setattro, /* tp_setattro */
|
|
+ 0, /* tp_as_buffer */
|
|
+ Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
+ 0, /* tp_doc */
|
|
+ (traverseproc)do_curl_traverse, /* tp_traverse */
|
|
+ (inquiry)do_curl_clear, /* tp_clear */
|
|
+ 0, /* tp_richcompare */
|
|
+ 0, /* tp_weaklistoffset */
|
|
+ 0, /* tp_iter */
|
|
+ 0, /* tp_iternext */
|
|
+ curlobject_methods, /* tp_methods */
|
|
+ 0, /* tp_members */
|
|
+ 0, /* tp_getset */
|
|
+ 0, /* tp_base */
|
|
+ 0, /* tp_dict */
|
|
+ 0, /* tp_descr_get */
|
|
+ 0, /* tp_descr_set */
|
|
+ 0, /* tp_dictoffset */
|
|
+ 0, /* tp_init */
|
|
+ 0, /* tp_alloc */
|
|
+ 0, /* tp_new */
|
|
+};
|
|
+#else
|
|
static PyTypeObject Curl_Type = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
@@ -3138,7 +3507,50 @@ static PyTypeObject Curl_Type = {
|
|
* safely ignore any compiler warnings about missing initializers.
|
|
*/
|
|
};
|
|
+#endif
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+static PyTypeObject CurlMulti_Type = {
|
|
+ PyVarObject_HEAD_INIT(NULL, 0)
|
|
+ "pycurl.CurlMulti", /* tp_name */
|
|
+ sizeof(CurlMultiObject), /* tp_basicsize */
|
|
+ 0, /* tp_itemsize */
|
|
+ (destructor)do_multi_dealloc,/* tp_dealloc */
|
|
+ 0, /* tp_print */
|
|
+ 0, // (getattrfunc)do_curl_getattr, /* tp_getattr */
|
|
+ 0, //(setattrfunc)do_curl_setattr, /* tp_setattr */
|
|
+ 0, /* tp_reserved */
|
|
+ 0, /* tp_repr */
|
|
+ 0, /* tp_as_number */
|
|
+ 0, /* tp_as_sequence */
|
|
+ 0, /* tp_as_mapping */
|
|
+ 0, /* tp_hash */
|
|
+ 0, /* tp_call */
|
|
+ 0, /* tp_str */
|
|
+ (getattrofunc)do_multi_getattro, //0, /* tp_getattro */
|
|
+ (setattrofunc)do_multi_setattro, /* tp_setattro */
|
|
+ 0, /* tp_as_buffer */
|
|
+ Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
+ 0, /* tp_doc */
|
|
+ (traverseproc)do_multi_traverse, /* tp_traverse */
|
|
+ (inquiry)do_multi_clear, /* tp_clear */
|
|
+ 0, /* tp_richcompare */
|
|
+ 0, /* tp_weaklistoffset */
|
|
+ 0, /* tp_iter */
|
|
+ 0, /* tp_iternext */
|
|
+ curlmultiobject_methods, /* tp_methods */
|
|
+ 0, /* tp_members */
|
|
+ 0, /* tp_getset */
|
|
+ 0, /* tp_base */
|
|
+ 0, /* tp_dict */
|
|
+ 0, /* tp_descr_get */
|
|
+ 0, /* tp_descr_set */
|
|
+ 0, /* tp_dictoffset */
|
|
+ 0, /* tp_init */
|
|
+ 0, /* tp_alloc */
|
|
+ 0, /* tp_new */
|
|
+};
|
|
+#else
|
|
static PyTypeObject CurlMulti_Type = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
@@ -3169,7 +3581,7 @@ static PyTypeObject CurlMulti_Type = {
|
|
* safely ignore any compiler warnings about missing initializers.
|
|
*/
|
|
};
|
|
-
|
|
+#endif
|
|
|
|
/*************************************************************************
|
|
// module level
|
|
@@ -3227,7 +3639,11 @@ static PyObject *vi_str(const char *s)
|
|
}
|
|
while (*s == ' ' || *s == '\t')
|
|
s++;
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ return PyUnicode_FromString(s);
|
|
+#else
|
|
return PyString_FromString(s);
|
|
+#endif
|
|
}
|
|
|
|
static PyObject *
|
|
@@ -3354,7 +3770,13 @@ insobj2(PyObject *dict1, PyObject *dict2, char *name, PyObject *value)
|
|
goto error;
|
|
if (value == NULL)
|
|
goto error;
|
|
+
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ key = PyUnicode_FromString(name);
|
|
+#else
|
|
key = PyString_FromString(name);
|
|
+#endif
|
|
+
|
|
if (key == NULL)
|
|
goto error;
|
|
#if 0
|
|
@@ -3381,7 +3803,11 @@ error:
|
|
static void
|
|
insstr(PyObject *d, char *name, char *value)
|
|
{
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ PyObject *v = PyUnicode_FromString(value);
|
|
+#else
|
|
PyObject *v = PyString_FromString(value);
|
|
+#endif
|
|
insobj2(d, NULL, name, v);
|
|
}
|
|
|
|
@@ -3414,6 +3840,20 @@ insint_m(PyObject *d, char *name, long value)
|
|
}
|
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+static PyModuleDef curlmodule = {
|
|
+ PyModuleDef_HEAD_INIT,
|
|
+ "pycurl",
|
|
+ module_doc,
|
|
+ -1,
|
|
+ curl_methods, NULL, NULL, NULL, NULL
|
|
+};
|
|
+#endif
|
|
+
|
|
+
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+PyMODINIT_FUNC PyInit_pycurl(void)
|
|
+#else
|
|
/* Initialization function for the module */
|
|
#if defined(PyMODINIT_FUNC)
|
|
PyMODINIT_FUNC
|
|
@@ -3424,6 +3864,7 @@ extern "C"
|
|
DL_EXPORT(void)
|
|
#endif
|
|
initpycurl(void)
|
|
+#endif
|
|
{
|
|
PyObject *m, *d;
|
|
const curl_version_info_data *vi;
|
|
@@ -3433,13 +3874,29 @@ initpycurl(void)
|
|
p_Curl_Type = &Curl_Type;
|
|
p_CurlMulti_Type = &CurlMulti_Type;
|
|
p_CurlShare_Type = &CurlShare_Type;
|
|
- Curl_Type.ob_type = &PyType_Type;
|
|
- CurlMulti_Type.ob_type = &PyType_Type;
|
|
- CurlShare_Type.ob_type = &PyType_Type;
|
|
+ Py_TYPE(&Curl_Type) = &PyType_Type;
|
|
+ Py_TYPE(&CurlMulti_Type) = &PyType_Type;
|
|
+ Py_TYPE(&CurlShare_Type) = &PyType_Type;
|
|
|
|
/* Create the module and add the functions */
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ if (PyType_Ready(&Curl_Type) < 0)
|
|
+ return NULL;
|
|
+
|
|
+ if (PyType_Ready(&CurlMulti_Type) < 0)
|
|
+ return NULL;
|
|
+
|
|
+
|
|
+ m = PyModule_Create(&curlmodule);
|
|
+ if (m == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ Py_INCREF(&Curl_Type);
|
|
+#else
|
|
+
|
|
m = Py_InitModule3("pycurl", curl_methods, module_doc);
|
|
assert(m != NULL && PyModule_Check(m));
|
|
+#endif
|
|
|
|
/* Add error object to the module */
|
|
d = PyModule_GetDict(m);
|
|
@@ -3906,6 +4363,9 @@ initpycurl(void)
|
|
/* Finally initialize global interpreter lock */
|
|
PyEval_InitThreads();
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
+ return m;
|
|
+#endif
|
|
}
|
|
|
|
/* vi:ts=4:et:nowrap
|
|
diff --git a/tests/test_internals.py b/tests/test_internals.py
|
|
index afcc53d..7c2f602 100644
|
|
--- a/tests/test_internals.py
|
|
+++ b/tests/test_internals.py
|
|
@@ -16,7 +16,10 @@ try:
|
|
except ImportError:
|
|
gc = None
|
|
import copy, os, sys
|
|
-from StringIO import StringIO
|
|
+try:
|
|
+ from io import StringIO
|
|
+except ImportError:
|
|
+ from StringIO import StringIO
|
|
try:
|
|
import cPickle
|
|
except ImportError:
|
|
@@ -41,10 +44,10 @@ if "-q" in sys.argv:
|
|
opts.verbose = opts.verbose - 1
|
|
|
|
|
|
-print "Python", sys.version
|
|
-print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM)
|
|
-print "PycURL version info", pycurl.version_info()
|
|
-print " %s, compiled %s" % (pycurl.__file__, pycurl.COMPILE_DATE)
|
|
+print("Python", sys.version)
|
|
+print("PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM))
|
|
+print("PycURL version info", pycurl.version_info())
|
|
+print(" %s, compiled %s" % (pycurl.__file__, pycurl.COMPILE_DATE))
|
|
|
|
|
|
# /***********************************************************************
|
|
@@ -148,13 +151,13 @@ if 1 and copy:
|
|
m = CurlMulti()
|
|
try:
|
|
copy.copy(c)
|
|
- except copy.Error:
|
|
+ except (copy.Error, TypeError):
|
|
pass
|
|
else:
|
|
assert 0, "internal error - copying should fail"
|
|
try:
|
|
copy.copy(m)
|
|
- except copy.Error:
|
|
+ except (copy.Error, TypeError):
|
|
pass
|
|
else:
|
|
assert 0, "internal error - copying should fail"
|
|
@@ -166,13 +169,13 @@ if 1 and pickle:
|
|
p = pickle.Pickler(fp, 1)
|
|
try:
|
|
p.dump(c)
|
|
- except pickle.PicklingError:
|
|
+ except (pickle.PicklingError, TypeError):
|
|
pass
|
|
else:
|
|
assert 0, "internal error - pickling should fail"
|
|
try:
|
|
p.dump(m)
|
|
- except pickle.PicklingError:
|
|
+ except (pickle.PicklingError, TypeError):
|
|
pass
|
|
else:
|
|
assert 0, "internal error - pickling should fail"
|
|
@@ -229,7 +232,9 @@ if 1 and gc:
|
|
c.m.c = c
|
|
# delete
|
|
gc.collect()
|
|
- flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS
|
|
+ flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE
|
|
+ if hasattr(gc, "DEBUG_OBJECTS"):
|
|
+ flags = flags | gc.DEBUG_OBJECTS
|
|
if opts.verbose >= 1:
|
|
flags = flags | gc.DEBUG_STATS
|
|
gc.set_debug(flags)
|
|
@@ -237,17 +242,17 @@ if 1 and gc:
|
|
##print gc.get_referrers(c)
|
|
##print gc.get_objects()
|
|
if opts.verbose >= 1:
|
|
- print "Tracked objects:", len(gc.get_objects())
|
|
+ print("Tracked objects:", len(gc.get_objects()))
|
|
# The `del' below should delete these 4 objects:
|
|
# Curl + internal dict, CurlMulti + internal dict
|
|
del c
|
|
gc.collect()
|
|
if opts.verbose >= 1:
|
|
- print "Tracked objects:", len(gc.get_objects())
|
|
+ print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
|
|
# /***********************************************************************
|
|
# // done
|
|
# ************************************************************************/
|
|
|
|
-print "All tests passed."
|
|
+print("All tests passed.")
|
|
diff --git a/tests/test_memleak.py b/tests/test_memleak.py
|
|
index 284df62..ad7bad1 100644
|
|
--- a/tests/test_memleak.py
|
|
+++ b/tests/test_memleak.py
|
|
@@ -12,20 +12,22 @@ import gc, pycurl, sys
|
|
gc.enable()
|
|
|
|
|
|
-print "Python", sys.version
|
|
-print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM)
|
|
+print("Python", sys.version)
|
|
+print("PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM))
|
|
##print "PycURL version info", pycurl.version_info()
|
|
-print " %s, compiled %s" % (pycurl.__file__, pycurl.COMPILE_DATE)
|
|
+print(" %s, compiled %s" % (pycurl.__file__, pycurl.COMPILE_DATE))
|
|
|
|
|
|
gc.collect()
|
|
-flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS
|
|
+flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE
|
|
+if hasattr(gc, "DEBUG_OBJECTS"):
|
|
+ flags = flags | gc.DEBUG_OBJECTS
|
|
if 1:
|
|
flags = flags | gc.DEBUG_STATS
|
|
gc.set_debug(flags)
|
|
gc.collect()
|
|
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
+print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
multi = pycurl.CurlMulti()
|
|
t = []
|
|
@@ -34,20 +36,20 @@ for a in range(100):
|
|
multi.add_handle(curl)
|
|
t.append(curl)
|
|
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
+print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
for curl in t:
|
|
curl.close()
|
|
multi.remove_handle(curl)
|
|
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
+print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
del curl
|
|
del t
|
|
del multi
|
|
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
+print("Tracked objects:", len(gc.get_objects()))
|
|
gc.collect()
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
+print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
|