File pycurl-python3.patch of Package python3-pycurl

diff -ruN ./examples/basicfirst.py ../pycurl-7.19.0.test/examples/basicfirst.py
--- ./examples/basicfirst.py	2005-02-11 19:09:11.000000000 +0800
+++ ../pycurl-7.19.0.test/examples/basicfirst.py	2012-04-28 15:30:41.041273003 +0900
@@ -13,13 +13,17 @@
     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 -ruN ./examples/retriever-multi.py ../pycurl-7.19.0.test/examples/retriever-multi.py
--- ./examples/retriever-multi.py	2005-07-28 20:04:13.000000000 +0900
+++ ../pycurl-7.19.0.test/examples/retriever-multi.py	2012-04-28 15:10:34.768799001 +0900
@@ -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 @@
     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 @@
 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 @@
         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 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 @@
     c.close()
 m.close()
 
+#time.sleep(30)
diff -ruN ./setup.py ../pycurl-7.19.0.test/setup.py
--- ./setup.py	2012-04-28 15:05:16.000000000 +0900
+++ ../pycurl-7.19.0.test/setup.py	2012-04-28 15:10:34.768799001 +0900
@@ -31,7 +31,7 @@
     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 @@
     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 @@
             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 @@
     # 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 @@
     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
@@ -208,4 +208,4 @@
     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 -ruN ./src/pycurl.c ../pycurl-7.19.0.test/src/pycurl.c
--- ./src/pycurl.c	2008-09-10 02:40:34.000000000 +0900
+++ ../pycurl-7.19.0.test/src/pycurl.c	2012-04-28 15:18:26.302305002 +0900
@@ -94,6 +94,17 @@
 static void pycurl_ssl_cleanup(void);
 #endif
 
+#if PY_MAJOR_VERSION < 3
+#define Py_TYPE(x) (x)->ob_type
+#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
+
 /* Calculate the number of OBJECTPOINT options we need to store */
 #define OPTIONS_SIZE    ((int)CURLOPT_LASTENTRY % 10000)
 #define MOPTIONS_SIZE   ((int)CURLMOPT_LASTENTRY % 10000)
@@ -158,6 +169,7 @@
     PyObject *opensocket_cb;
     /* file objects */
     PyObject *readdata_fp;
+    PyObject *writedata;
     PyObject *writedata_fp;
     PyObject *writeheader_fp;
     /* misc */
@@ -199,16 +211,46 @@
 #  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));
+	PyUnicode_AsWideChar((PyUnicodeObject *) obj, str, pysize);
+	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);
@@ -233,7 +275,11 @@
         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);
@@ -269,7 +315,7 @@
      */
     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() */
@@ -299,7 +345,7 @@
      */
     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() */
@@ -315,7 +361,7 @@
 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);
 }
 
@@ -325,7 +371,7 @@
 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);
 }
 
@@ -335,7 +381,7 @@
 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);
     }
@@ -553,6 +599,7 @@
     share_lock_unlock(share->lock, data);
 }
 
+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 CurlShareObject *
@@ -673,7 +720,8 @@
 
     /* 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;
         }
@@ -806,11 +854,23 @@
     }
     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;
 }
@@ -877,7 +937,7 @@
     /* 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) {
@@ -962,7 +1022,12 @@
         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
 }
 
 
@@ -1122,6 +1187,52 @@
     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)
 {
@@ -1163,6 +1274,7 @@
 	    ret = CURL_SOCKET_BAD;
 	    goto verbose_error;
 	}
+
 	// normal operation:
 	if (PyInt_Check(fileno_result)) {
 	    ret = dup(PyInt_AsLong(fileno_result));
@@ -1224,11 +1336,19 @@
         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;
@@ -1401,6 +1521,7 @@
     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) {
@@ -1584,7 +1705,11 @@
 #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;
@@ -1633,8 +1758,13 @@
                 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);
@@ -1683,7 +1813,6 @@
     /* 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))
@@ -1724,7 +1853,12 @@
 #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)) {
+#endif
         FILE *fp;
 
         /* Ensure the option specified a file as well as the input */
@@ -1742,7 +1876,12 @@
             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
         fp = PyFile_AsFile(obj);
         if (fp == NULL) {
             PyErr_SetString(PyExc_TypeError, "second argument must be open file");
@@ -1752,6 +1891,7 @@
         if (res != CURLE_OK) {
             CURLERROR_RETVAL();
         }
+#endif
         Py_INCREF(obj);
 
         switch (option) {
@@ -1841,14 +1981,27 @@
                     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,
@@ -1902,7 +2055,11 @@
                             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);
@@ -1920,7 +2077,11 @@
                             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;
@@ -1972,7 +2133,11 @@
             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;
@@ -2187,7 +2352,12 @@
                 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:
@@ -2846,7 +3016,7 @@
             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 ??? */
         }
@@ -2927,7 +3097,6 @@
          *       socket code to report any errors.
          */
     }
-
     return PyInt_FromLong(n);
 }
 
@@ -2992,6 +3161,116 @@
 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)
 {
@@ -3026,6 +3305,7 @@
     return Py_FindMethod(m, co, name);
 }
 
+
 static int
 do_share_setattr(CurlShareObject *so, char *name, PyObject *v)
 {
@@ -3070,10 +3350,53 @@
     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 */
@@ -3104,7 +3427,50 @@
      * 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 */
@@ -3135,7 +3501,50 @@
      * 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 */
@@ -3166,7 +3575,7 @@
      * safely ignore any compiler warnings about missing initializers.
      */
 };
-
+#endif
 
 /*************************************************************************
 // module level
@@ -3224,7 +3633,11 @@
     }
     while (*s == ' ' || *s == '\t')
         s++;
+#if PY_MAJOR_VERSION >= 3
+    return PyUnicode_FromString(s);
+#else
     return PyString_FromString(s);
+#endif
 }
 
 static PyObject *
@@ -3351,7 +3764,13 @@
         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
@@ -3378,7 +3797,11 @@
 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);
 }
 
@@ -3411,6 +3834,20 @@
 }
 
 
+#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
@@ -3421,6 +3858,7 @@
 DL_EXPORT(void)
 #endif
 initpycurl(void)
+#endif
 {
     PyObject *m, *d;
     const curl_version_info_data *vi;
@@ -3430,13 +3868,29 @@
     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);
@@ -3903,6 +4357,9 @@
     /* Finally initialize global interpreter lock */
     PyEval_InitThreads();
 
+#if PY_MAJOR_VERSION >= 3
+	return m;
+#endif
 }
 
 /* vi:ts=4:et:nowrap
openSUSE Build Service is sponsored by