--- /dev/null
+From 05433632fb1ccdabc1d29d78f32bc35de0a8638b Mon Sep 17 00:00:00 2001
+From: kjetilja <kjetilja>
+Date: Mon, 29 Sep 2008 10:56:57 +0000
+Subject: [PATCH 1/5] No longer keep copies of string options since this is managed by libcurl
+
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ ChangeLog | 12 +++++++++-
+ src/pycurl.c | 60 +--------------------------------------------------------
+ 2 files changed, 12 insertions(+), 60 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 0fb7f8c..618654d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,7 +1,15 @@
+-Version 7.19.0 [requires libcurl-7.19.0 or better]
++Version 7.19.1 [requires libcurl-7.19.0 or better]
+ --------------
+
+- * Added CURLFILE, ADDRESS_SCOPE and ISSUERCERT options,
++ * No longer keep string options copies in the
++ Curl Python objects, since string options are
++ now managed by libcurl.
++
++
++Version 7.19.0
++--------------
++
++ * Added CURLFILE, ADDRESS_SCOPE and ISSUERCERT options,
+ as well as the APPCONNECT_TIME info.
+
+ * Added PRIMARY_IP info (patch by
+diff --git a/src/pycurl.c b/src/pycurl.c
+index a17a23b..6de1514 100644
+--- a/src/pycurl.c
++++ b/src/pycurl.c
+@@ -1,4 +1,4 @@
+-/* $Id: pycurl.c,v 1.147 2008/09/09 17:40:34 kjetilja Exp $ */
++/* $Id: pycurl.c,v 1.148 2008/09/29 10:56:57 kjetilja Exp $ */
+
+ /* PycURL -- cURL Python module
+ *
+@@ -97,12 +97,6 @@ static void pycurl_ssl_cleanup(void);
+ /* Calculate the number of OBJECTPOINT options we need to store */
+ #define OPTIONS_SIZE ((int)CURLOPT_LASTENTRY % 10000)
+ #define MOPTIONS_SIZE ((int)CURLMOPT_LASTENTRY % 10000)
+-static int OPT_INDEX(int o)
+-{
+- assert(o >= CURLOPTTYPE_OBJECTPOINT);
+- assert(o < CURLOPTTYPE_OBJECTPOINT + OPTIONS_SIZE);
+- return o - CURLOPTTYPE_OBJECTPOINT;
+-}
+
+ /* Type objects */
+ static PyObject *ErrorObject = NULL;
+@@ -161,7 +155,6 @@ typedef struct {
+ PyObject *writedata_fp;
+ PyObject *writeheader_fp;
+ /* misc */
+- void *options[OPTIONS_SIZE]; /* for OBJECTPOINT options */
+ char error[CURL_ERROR_SIZE+1];
+ } CurlObject;
+
+@@ -741,7 +734,6 @@ util_curl_new(void)
+ self->writeheader_fp = NULL;
+
+ /* Zero string pointer memory buffer used by setopt */
+- memset(self->options, 0, sizeof(self->options));
+ memset(self->error, 0, sizeof(self->error));
+
+ return self;
+@@ -804,7 +796,6 @@ do_curl_new(PyObject *dummy)
+ free(s);
+ goto error;
+ }
+- self->options[ OPT_INDEX(CURLOPT_USERAGENT) ] = s; s = NULL;
+
+ /* Success - return new object */
+ return self;
+@@ -872,7 +863,6 @@ static void
+ util_curl_close(CurlObject *self)
+ {
+ CURL *handle;
+- int i;
+
+ /* Zero handle and thread-state to disallow any operations to be run
+ * from now on */
+@@ -916,16 +906,6 @@ util_curl_close(CurlObject *self)
+ SFREE(self->postquote);
+ SFREE(self->prequote);
+ #undef SFREE
+-
+- /* Last, free the options. This must be done after the curl handle
+- * is closed since libcurl assumes that some options are valid when
+- * invoking curl_easy_cleanup(). */
+- for (i = 0; i < OPTIONS_SIZE; i++) {
+- if (self->options[i] != NULL) {
+- free(self->options[i]);
+- self->options[i] = NULL;
+- }
+- }
+ }
+
+
+@@ -1424,8 +1404,6 @@ verbose_error:
+ static PyObject*
+ do_curl_reset(CurlObject *self)
+ {
+- unsigned int i;
+-
+ curl_easy_reset(self->handle);
+
+ /* Decref callbacks and file handles */
+@@ -1443,15 +1421,6 @@ do_curl_reset(CurlObject *self)
+ SFREE(self->postquote);
+ SFREE(self->prequote);
+ #undef SFREE
+-
+- /* Last, free the options */
+- for (i = 0; i < OPTIONS_SIZE; i++) {
+- if (self->options[i] != NULL) {
+- free(self->options[i]);
+- self->options[i] = NULL;
+- }
+- }
+-
+ return Py_None;
+ }
+
+@@ -1461,7 +1430,6 @@ static PyObject *
+ util_curl_unsetopt(CurlObject *self, int option)
+ {
+ int res;
+- int opt_index = -1;
+
+ #define SETOPT2(o,x) \
+ if ((res = curl_easy_setopt(self->handle, (o), (x))) != CURLE_OK) goto error
+@@ -1502,7 +1470,6 @@ util_curl_unsetopt(CurlObject *self, int option)
+ case CURLOPT_SSL_CIPHER_LIST:
+ case CURLOPT_USERPWD:
+ SETOPT((char *) 0);
+- opt_index = OPT_INDEX(option);
+ break;
+
+ /* info: we explicitly list unsupported options here */
+@@ -1512,11 +1479,6 @@ util_curl_unsetopt(CurlObject *self, int option)
+ return NULL;
+ }
+
+- if (opt_index >= 0 && self->options[opt_index] != NULL) {
+- free(self->options[opt_index]);
+- self->options[opt_index] = NULL;
+- }
+-
+ Py_INCREF(Py_None);
+ return Py_None;
+
+@@ -1587,8 +1549,6 @@ do_curl_setopt(CurlObject *self, PyObject *args)
+ if (PyString_Check(obj)) {
+ char *str = NULL;
+ Py_ssize_t len = -1;
+- char *buf;
+- int opt_index;
+
+ /* Check that the option specified a string as well as the input */
+ switch (option) {
+@@ -1651,28 +1611,12 @@ do_curl_setopt(CurlObject *self, PyObject *args)
+ }
+ /* Allocate memory to hold the string */
+ assert(str != NULL);
+- if (len <= 0)
+- buf = strdup(str);
+- else {
+- buf = (char *) malloc(len);
+- if (buf) memcpy(buf, str, len);
+- }
+- if (buf == NULL)
+- return PyErr_NoMemory();
+ /* Call setopt */
+- res = curl_easy_setopt(self->handle, (CURLoption)option, buf);
++ res = curl_easy_setopt(self->handle, (CURLoption)option, str);
+ /* Check for errors */
+ if (res != CURLE_OK) {
+- free(buf);
+ CURLERROR_RETVAL();
+ }
+- /* Save allocated option buffer */
+- opt_index = OPT_INDEX(option);
+- if (self->options[opt_index] != NULL) {
+- free(self->options[opt_index]);
+- self->options[opt_index] = NULL;
+- }
+- self->options[opt_index] = buf;
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+--
+1.7.1
+
--- /dev/null
+From 009e170d2838346461ff0b31b0afa44f3d6278f3 Mon Sep 17 00:00:00 2001
+From: zanee <zanee>
+Date: Fri, 23 Apr 2010 16:06:41 +0000
+Subject: [PATCH 2/5] Fixes https://sourceforge.net/tracker/?func=detail&aid=2812016&group_id=28236&atid=392777 with applied patch from sourceforge user dbprice1.
+
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ setup.py | 23 ++++++++++++++++++-----
+ 1 files changed, 18 insertions(+), 5 deletions(-)
+
+diff --git a/setup.py b/setup.py
+index 0ffd9d2..76b9d58 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1,7 +1,7 @@
+ #! /usr/bin/env python
+ # -*- coding: iso-8859-1 -*-
+ # vi:ts=4:et
+-# $Id: setup.py,v 1.150 2008/09/09 17:40:34 kjetilja Exp $
++# $Id: setup.py,v 1.151 2010/04/23 16:06:41 zanee Exp $
+
+ """Setup script for the PycURL module distribution."""
+
+@@ -9,7 +9,7 @@ PACKAGE = "pycurl"
+ PY_PACKAGE = "curl"
+ VERSION = "7.19.0"
+
+-import glob, os, re, sys, string
++import glob, os, re, sys, string, subprocess
+ import distutils
+ from distutils.core import setup
+ from distutils.extension import Extension
+@@ -96,9 +96,22 @@ else:
+ include_dirs.append(e[2:])
+ else:
+ extra_compile_args.append(e)
+- libs = split_quoted(
+- os.popen("'%s' --libs" % CURL_CONFIG).read()+\
+- os.popen("'%s' --static-libs" % CURL_CONFIG).read())
++
++ # Run curl-config --libs and --static-libs. Some platforms may not
++ # support one or the other of these curl-config options, so gracefully
++ # tolerate failure of either, but not both.
++ optbuf = ""
++ for option in ["--libs", "--static-libs"]:
++ p = subprocess.Popen("'%s' %s" % (CURL_CONFIG, option), shell=True,
++ stdout=subprocess.PIPE)
++ (stdout, stderr) = p.communicate()
++ if p.wait() == 0:
++ optbuf += stdout
++ if optbuf == "":
++ raise Exception, ("Neither of curl-config --libs or --static-libs" +
++ "produced output")
++ libs = split_quoted(optbuf)
++
+ for e in libs:
+ if e[:2] == "-l":
+ libraries.append(e[2:])
+--
+1.7.1
+
--- /dev/null
+From 4a377e2d60fb903e91a370595a6ea22cb7ee0e0e Mon Sep 17 00:00:00 2001
+From: zanee <zanee>
+Date: Wed, 28 Apr 2010 16:02:41 +0000
+Subject: [PATCH 3/5 v2] Fixes refcount bug and provides better organization of PyCurl object. Submitted by dbprice1.
+
+https://sourceforge.net/tracker/?func=detail&aid=2893665&group_id=28236&atid=392777
+
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ src/pycurl.c | 88 +++++++++++++++++++++++++++++++++++++--------------------
+ 1 files changed, 57 insertions(+), 31 deletions(-)
+
+diff --git a/src/pycurl.c b/src/pycurl.c
+index 6de1514..32c7ca5 100644
+--- a/src/pycurl.c
++++ b/src/pycurl.c
+@@ -1,4 +1,4 @@
+-/* $Id: pycurl.c,v 1.148 2008/09/29 10:56:57 kjetilja Exp $ */
++/* $Id: pycurl.c,v 1.149 2010/04/28 16:02:41 zanee Exp $ */
+
+ /* PycURL -- cURL Python module
+ *
+@@ -739,64 +739,80 @@ util_curl_new(void)
+ return self;
+ }
+
+-
+-/* constructor - this is a module-level function returning a new instance */
+-static CurlObject *
+-do_curl_new(PyObject *dummy)
++/* initializer - used to intialize curl easy handles for use with pycurl */
++static int
++util_curl_init(CurlObject *self)
+ {
+- CurlObject *self = NULL;
+ int res;
+ char *s = NULL;
+
+- UNUSED(dummy);
+-
+- /* Allocate python curl object */
+- self = util_curl_new();
+- if (self == NULL)
+- return NULL;
+-
+- /* Initialize curl handle */
+- self->handle = curl_easy_init();
+- if (self->handle == NULL)
+- goto error;
+-
+ /* Set curl error buffer and zero it */
+ res = curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->error);
+- if (res != CURLE_OK)
+- goto error;
++ if (res != CURLE_OK) {
++ return (-1);
++ }
+ memset(self->error, 0, sizeof(self->error));
+
+ /* Set backreference */
+ res = curl_easy_setopt(self->handle, CURLOPT_PRIVATE, (char *) self);
+- if (res != CURLE_OK)
+- goto error;
++ if (res != CURLE_OK) {
++ return (-1);
++ }
+
+ /* Enable NOPROGRESS by default, i.e. no progress output */
+ res = curl_easy_setopt(self->handle, CURLOPT_NOPROGRESS, (long)1);
+- if (res != CURLE_OK)
+- goto error;
++ if (res != CURLE_OK) {
++ return (-1);
++ }
+
+ /* Disable VERBOSE by default, i.e. no verbose output */
+ res = curl_easy_setopt(self->handle, CURLOPT_VERBOSE, (long)0);
+- if (res != CURLE_OK)
+- goto error;
++ if (res != CURLE_OK) {
++ return (-1);
++ }
+
+ /* Set FTP_ACCOUNT to NULL by default */
+ res = curl_easy_setopt(self->handle, CURLOPT_FTP_ACCOUNT, NULL);
+- if (res != CURLE_OK)
+- goto error;
++ if (res != CURLE_OK) {
++ return (-1);
++ }
+
+ /* Set default USERAGENT */
+ s = (char *) malloc(7 + strlen(LIBCURL_VERSION) + 1);
+- if (s == NULL)
+- goto error;
++ if (s == NULL) {
++ return (-1);
++ }
+ strcpy(s, "PycURL/"); strcpy(s+7, LIBCURL_VERSION);
+ res = curl_easy_setopt(self->handle, CURLOPT_USERAGENT, (char *) s);
+ if (res != CURLE_OK) {
+ free(s);
+- goto error;
++ return (-1);
+ }
++ return (0);
++}
++
++/* constructor - this is a module-level function returning a new instance */
++static CurlObject *
++do_curl_new(PyObject *dummy)
++{
++ CurlObject *self = NULL;
++ int res;
++
++ UNUSED(dummy);
++
++ /* Allocate python curl object */
++ self = util_curl_new();
++ if (self == NULL)
++ return NULL;
++
++ /* Initialize curl handle */
++ self->handle = curl_easy_init();
++ if (self->handle == NULL)
++ goto error;
+
++ res = util_curl_init(self);
++ if (res < 0)
++ goto error;
+ /* Success - return new object */
+ return self;
+
+@@ -1404,6 +1420,8 @@ verbose_error:
+ static PyObject*
+ do_curl_reset(CurlObject *self)
+ {
++ int res;
++
+ curl_easy_reset(self->handle);
+
+ /* Decref callbacks and file handles */
+@@ -1421,6 +1439,14 @@ do_curl_reset(CurlObject *self)
+ SFREE(self->postquote);
+ SFREE(self->prequote);
+ #undef SFREE
++ res = util_curl_init(self);
++ if (res < 0) {
++ Py_DECREF(self); /* this also closes self->handle */
++ PyErr_SetString(ErrorObject, "resetting curl failed");
++ return NULL;
++ }
++
++ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+--
+1.7.1
+
--- /dev/null
+From 206c15ea32e05ae98827d00626a101e33a7bec70 Mon Sep 17 00:00:00 2001
+From: zanee <zanee>
+Date: Wed, 28 Apr 2010 16:03:40 +0000
+Subject: [PATCH 4/5] Test for reset fixes refcount bug
+
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ tests/test_reset.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 74 insertions(+), 0 deletions(-)
+ create mode 100644 tests/test_reset.py
+
+diff --git a/tests/test_reset.py b/tests/test_reset.py
+new file mode 100644
+index 0000000..c350d17
+--- /dev/null
++++ b/tests/test_reset.py
+@@ -0,0 +1,74 @@
++#!/usr/bin/python
++
++import sys
++import pycurl
++
++saw_error = 1
++
++def main():
++ global saw_error
++
++ pycurl.global_init(pycurl.GLOBAL_DEFAULT)
++
++ outf = file("/dev/null", "rb+")
++ cm = pycurl.CurlMulti()
++
++ # Set multi handle's options
++ cm.setopt(pycurl.M_PIPELINING, 1)
++
++ eh = pycurl.Curl()
++
++ for x in range(1, 20):
++
++ eh.setopt(pycurl.WRITEDATA, outf)
++ eh.setopt(pycurl.URL, sys.argv[1])
++ cm.add_handle(eh)
++
++ while 1:
++ ret, active_handles = cm.perform()
++ if ret != pycurl.E_CALL_MULTI_PERFORM:
++ break
++
++ while active_handles:
++ ret = cm.select(1.0)
++ if ret == -1:
++ continue
++ while 1:
++ ret, active_handles = cm.perform()
++ if ret != pycurl.E_CALL_MULTI_PERFORM:
++ break
++
++ count, good, bad = cm.info_read()
++
++ for h, en, em in bad:
++ print "Transfer to %s failed with %d, %s\n" % \
++ (h.getinfo(pycurl.EFFECTIVE_URL), en, em)
++ raise RuntimeError
++
++ for h in good:
++ httpcode = h.getinfo(pycurl.RESPONSE_CODE)
++ if httpcode != 200:
++ print "Transfer to %s failed with code %d\n" %\
++ (h.getinfo(pycurl.EFFECTIVE_URL), httpcode)
++ raise RuntimeError
++
++ else:
++ print "Recd %d bytes from %s" % \
++ (h.getinfo(pycurl.SIZE_DOWNLOAD),
++ h.getinfo(pycurl.EFFECTIVE_URL))
++
++ cm.remove_handle(eh)
++ eh.reset()
++
++ eh.close()
++ cm.close()
++ outf.close()
++
++ pycurl.global_cleanup()
++
++
++if __name__ == '__main__':
++ if len(sys.argv) != 2:
++ print "Usage: %s <url>" % sys.argv[0]
++ sys.exit(2)
++ main()
+--
+1.7.1
+
--- /dev/null
+From d075bfb8a5207f933a5a704becd7f64e8521dc28 Mon Sep 17 00:00:00 2001
+From: zanee <zanee>
+Date: Tue, 4 May 2010 18:47:08 +0000
+Subject: [PATCH 5/5] Updating ChangeLog with relevant changes
+
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ ChangeLog | 11 +++++++++++
+ 1 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 618654d..885c8b0 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,14 @@
++Version 7.19.2
++--------------
++
++ * Cleaned up website
++
++ * Fix pycurl.reset() (patch by <johansen at sun.com>).
++
++ * Fix install routine in setup.py where
++ certain platforms (Solaris, Mac OSX, etc)
++ would search for a static copy of libcurl (dbp)
++
+ Version 7.19.1 [requires libcurl-7.19.0 or better]
+ --------------
+
+--
+1.7.1
+
--- /dev/null
+From 0796c0530648ae0e741a20a78d1fcf315783c178 Mon Sep 17 00:00:00 2001
+From: Kamil Dudka <kdudka@redhat.com>
+Date: Mon, 25 Feb 2013 19:48:22 +0100
+Subject: [PATCH 1/2] setup.py: do not use curl-config --static-libs
+
+---
+ setup.py | 5 ++---
+ 1 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/setup.py b/setup.py
+index 76b9d58..86a2951 100644
+--- a/setup.py
++++ b/setup.py
+@@ -101,15 +101,14 @@ else:
+ # support one or the other of these curl-config options, so gracefully
+ # tolerate failure of either, but not both.
+ optbuf = ""
+- for option in ["--libs", "--static-libs"]:
++ for option in ["--libs"]:
+ p = subprocess.Popen("'%s' %s" % (CURL_CONFIG, option), shell=True,
+ stdout=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.wait() == 0:
+ optbuf += stdout
+ if optbuf == "":
+- raise Exception, ("Neither of curl-config --libs or --static-libs" +
+- "produced output")
++ raise Exception, ("curl-config --libs did not produce output")
+ libs = split_quoted(optbuf)
+
+ for e in libs:
+--
+1.7.1
+
--- /dev/null
+From 0bd83ea6c820db26f98936e6e017d39fb214cbd0 Mon Sep 17 00:00:00 2001
+From: Kamil Dudka <kdudka@redhat.com>
+Date: Mon, 25 Feb 2013 19:50:18 +0100
+Subject: [PATCH 2/2] test_internals.py: add a test for ref-counting of reset()
+
+---
+ tests/test_internals.py | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/tests/test_internals.py b/tests/test_internals.py
+index afcc53d..d026952 100644
+--- a/tests/test_internals.py
++++ b/tests/test_internals.py
+@@ -245,6 +245,11 @@ if 1 and gc:
+ if opts.verbose >= 1:
+ print "Tracked objects:", len(gc.get_objects())
+
++if 1:
++ # Ensure that the refcounting error in "reset" is fixed:
++ for i in xrange(100000):
++ c = Curl()
++ c.reset()
+
+ # /***********************************************************************
+ # // done
+--
+1.7.1
+
+++ /dev/null
---- a/src/pycurl.c
-+++ a/src/pycurl.c
-@@ -1452,6 +1452,7 @@ do_curl_reset(CurlObject *self)
- }
- }
-
-+ Py_INCREF(Py_None);
- return Py_None;
- }
-
---- a/tests/test_internals.py
-+++ a/tests/test_internals.py
-@@ -245,6 +245,11 @@ if 1 and gc:
- if opts.verbose >= 1:
- print "Tracked objects:", len(gc.get_objects())
-
-+if 1:
-+ # Ensure that the refcounting error in "reset" is fixed:
-+ for i in xrange(100000):
-+ c = Curl()
-+ c.reset()
-
- # /***********************************************************************
- # // done
+++ /dev/null
---- setup.py~ 2008-04-22 17:00:45.000000000 +0300
-+++ setup.py 2008-07-03 21:53:36.000000000 +0300
-@@ -97,8 +97,7 @@
- else:
- extra_compile_args.append(e)
- libs = split_quoted(
-- os.popen("'%s' --libs" % CURL_CONFIG).read()+\
-- os.popen("'%s' --static-libs" % CURL_CONFIG).read())
-+ os.popen("'%s' --libs" % CURL_CONFIG).read())
- for e in libs:
- if e[:2] == "-l":
- libraries.append(e[2:])
name = python-pycurl
version = 7.19.0
-release = 4
+release = 5
thisapp = pycurl-%{version}
groups = Development/Languages
license = LGPLv2+ or MIT
summary = A Python interface to libcurl.
-# During its initialization, PycURL checks that the actual libcurl version
-# is not lower than the one used when PycURL was built.
-# Yes, that should be handled by library versioning (which would then get
-# automatically reflected).
-# For now, we have to reflect that dependency.
-LIBCURL_VERSION = $(shell curl-config --version | awk '{ print $NF }')
-PKG_DEPS += libcurl>=%{LIBCURL_VERSION}
-
description
PycURL is a Python interface to libcurl. PycURL can be used to fetch
objects identified by a URL from a Python program, similar to the
packages
package %{name}
+ # During its initialization, PycURL checks that the actual libcurl version
+ # is not lower than the one used when PycURL was built.
+ # Yes, that should be handled by library versioning (which would then get
+ # automatically reflected).
+ # For now, we have to reflect that dependency.
+ requires
+ libcurl >= %(curl-config --version | awk '{ print $NF }')
+ end
+ end
package %{name}-debuginfo
template DEBUGINFO