12437 lines
376 KiB
Diff
12437 lines
376 KiB
Diff
From 9a426178c83f756ec248e9fd0010030ae7c62f2a Mon Sep 17 00:00:00 2001
|
|
From: Kjetil Jacobsen <kjetilja@gmail.com>
|
|
Date: Tue, 9 Sep 2008 18:49:59 +0000
|
|
Subject: [PATCH 001/149] whitespace
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
ChangeLog | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/ChangeLog b/ChangeLog
|
|
index 0fb7f8c..3d68424 100644
|
|
--- a/ChangeLog
|
|
+++ b/ChangeLog
|
|
@@ -1,7 +1,7 @@
|
|
Version 7.19.0 [requires libcurl-7.19.0 or better]
|
|
--------------
|
|
|
|
- * Added CURLFILE, ADDRESS_SCOPE and ISSUERCERT options,
|
|
+ * Added CURLFILE, ADDRESS_SCOPE and ISSUERCERT options,
|
|
as well as the APPCONNECT_TIME info.
|
|
|
|
* Added PRIMARY_IP info (patch by
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From b5f6dd9fd839e54db567d0451483a400edad60a4 Mon Sep 17 00:00:00 2001
|
|
From: Kjetil Jacobsen <kjetilja@gmail.com>
|
|
Date: Mon, 29 Sep 2008 10:56:57 +0000
|
|
Subject: [PATCH 002/149] No longer keep copies of string options since this is managed by libcurl
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
ChangeLog | 10 +++++++++-
|
|
src/pycurl.c | 58 +---------------------------------------------------------
|
|
2 files changed, 10 insertions(+), 58 deletions(-)
|
|
|
|
diff --git a/ChangeLog b/ChangeLog
|
|
index 3d68424..618654d 100644
|
|
--- a/ChangeLog
|
|
+++ b/ChangeLog
|
|
@@ -1,4 +1,12 @@
|
|
-Version 7.19.0 [requires libcurl-7.19.0 or better]
|
|
+Version 7.19.1 [requires libcurl-7.19.0 or better]
|
|
+--------------
|
|
+
|
|
+ * 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,
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 50ec9ce..189f5d6 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -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
|
|
|
|
|
|
From f241a60acc67cc8cbf3d36a2f3d55e1abf88bc33 Mon Sep 17 00:00:00 2001
|
|
From: Christopher Warner <cwarner@kernelcode.com>
|
|
Date: Fri, 23 Apr 2010 16:06:41 +0000
|
|
Subject: [PATCH 003/149] 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 | 21 +++++++++++++++++----
|
|
1 files changed, 17 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/setup.py b/setup.py
|
|
index 1c3831b..632399d 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -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
|
|
|
|
|
|
From 70114226c76ee06c6bacb488734796551ac9b2f9 Mon Sep 17 00:00:00 2001
|
|
From: Christopher Warner <cwarner@kernelcode.com>
|
|
Date: Wed, 28 Apr 2010 16:02:41 +0000
|
|
Subject: [PATCH 004/149] 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 | 87 ++++++++++++++++++++++++++++++++++++++--------------------
|
|
1 files changed, 57 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 189f5d6..47de850 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -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,10 +1439,19 @@ 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;
|
|
}
|
|
|
|
/* --------------- unsetopt/setopt/getinfo --------------- */
|
|
+ int res;
|
|
|
|
static PyObject *
|
|
util_curl_unsetopt(CurlObject *self, int option)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From a607b0c9f4676858fcf6335e9fb0c9ed6a9c3069 Mon Sep 17 00:00:00 2001
|
|
From: Christopher Warner <cwarner@kernelcode.com>
|
|
Date: Wed, 28 Apr 2010 16:03:40 +0000
|
|
Subject: [PATCH 005/149] Test for reset fixes refcount bug
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/test_reset.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 75 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..1addcfe
|
|
--- /dev/null
|
|
+++ b/tests/test_reset.py
|
|
@@ -0,0 +1,75 @@
|
|
+#!/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
|
|
|
|
|
|
From f773340ec40d5988d4a5b75e64b898dbe4a89800 Mon Sep 17 00:00:00 2001
|
|
From: Christopher Warner <cwarner@kernelcode.com>
|
|
Date: Wed, 28 Apr 2010 16:06:35 +0000
|
|
Subject: [PATCH 006/149] Added myself to the list of maintainers
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
setup.py | 4 ++--
|
|
1 files changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/setup.py b/setup.py
|
|
index 632399d..33704ef 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -197,8 +197,8 @@ setup_args = get_kw(
|
|
description="PycURL -- cURL library module for Python",
|
|
author="Kjetil Jacobsen, Markus F.X.J. Oberhumer",
|
|
author_email="kjetilja at gmail.com, markus at oberhumer.com",
|
|
- maintainer="Kjetil Jacobsen, Markus F.X.J. Oberhumer",
|
|
- maintainer_email="kjetilja at gmail.com, markus at oberhumer.com",
|
|
+ maintainer="Kjetil Jacobsen, Markus F.X.J. Oberhumer, Christopher Warner",
|
|
+ maintainer_email="kjetilja at gmail.com, markus at oberhumer.com, cwarner at kernelcode.com",
|
|
url="http://pycurl.sourceforge.net/",
|
|
license="LGPL/MIT",
|
|
data_files=get_data_files(),
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 67e0b9ac7c521b39d7dc779a79d21009f5619fa1 Mon Sep 17 00:00:00 2001
|
|
From: Christopher Warner <cwarner@kernelcode.com>
|
|
Date: Tue, 4 May 2010 18:47:08 +0000
|
|
Subject: [PATCH 007/149] 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
|
|
|
|
|
|
From 310638226dbe77b71a8eb9f8da58cf15d236337a Mon Sep 17 00:00:00 2001
|
|
From: Christopher Warner <cwarner@kernelcode.com>
|
|
Date: Wed, 13 Oct 2010 15:53:40 +0000
|
|
Subject: [PATCH 008/149] Added CURLOPT_SEEKFUNCTION, CURLOPT_SEEKDATA
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
1 files changed, 88 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 47de850..ac448b0 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -150,6 +150,7 @@ typedef struct {
|
|
PyObject *debug_cb;
|
|
PyObject *ioctl_cb;
|
|
PyObject *opensocket_cb;
|
|
+ PyObject *seek_cb;
|
|
/* file objects */
|
|
PyObject *readdata_fp;
|
|
PyObject *writedata_fp;
|
|
@@ -727,6 +728,7 @@ util_curl_new(void)
|
|
self->debug_cb = NULL;
|
|
self->ioctl_cb = NULL;
|
|
self->opensocket_cb = NULL;
|
|
+ self->seek_cb = NULL;
|
|
|
|
/* Set file object pointers to NULL by default */
|
|
self->readdata_fp = NULL;
|
|
@@ -1181,6 +1183,82 @@ verbose_error:
|
|
goto silent_error;
|
|
}
|
|
|
|
+static int
|
|
+seek_callback(void *stream, curl_off_t offset, int origin)
|
|
+{
|
|
+ CurlObject *self;
|
|
+ PyThreadState *tmp_state;
|
|
+ PyObject *arglist;
|
|
+ PyObject *result = NULL;
|
|
+ int ret = 2; /* assume error 2 (can't seek, libcurl free to work around). */
|
|
+ PyObject *cb;
|
|
+ int source = 0; /* assume beginning */
|
|
+
|
|
+ /* acquire thread */
|
|
+ self = (CurlObject *)stream;
|
|
+ tmp_state = get_thread_state(self);
|
|
+ if (tmp_state == NULL)
|
|
+ return ret;
|
|
+ PyEval_AcquireThread(tmp_state);
|
|
+
|
|
+ /* check arguments */
|
|
+ switch (origin)
|
|
+ {
|
|
+ case SEEK_SET:
|
|
+ source = 0;
|
|
+ break;
|
|
+ case SEEK_CUR:
|
|
+ source = 1;
|
|
+ break;
|
|
+ case SEEK_END:
|
|
+ source = 2;
|
|
+ break;
|
|
+ default:
|
|
+ source = origin;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* run callback */
|
|
+ cb = self->seek_cb;
|
|
+ if (cb == NULL)
|
|
+ goto silent_error;
|
|
+ arglist = Py_BuildValue("(i,i)", offset, source);
|
|
+ if (arglist == NULL)
|
|
+ goto verbose_error;
|
|
+ result = PyEval_CallObject(cb, arglist);
|
|
+ Py_DECREF(arglist);
|
|
+ if (result == NULL)
|
|
+ goto verbose_error;
|
|
+
|
|
+ /* handle result */
|
|
+ if (result == Py_None) {
|
|
+ ret = 0; /* None means success */
|
|
+ }
|
|
+ else if (PyInt_Check(result)) {
|
|
+ int ret_code = PyInt_AsLong(result);
|
|
+ if (ret_code < 0 || ret_code > 2) {
|
|
+ PyErr_Format(ErrorObject, "invalid return value for seek callback %d not in (0, 1, 2)", ret_code);
|
|
+ goto verbose_error;
|
|
+ }
|
|
+ ret = ret_code; /* pass the return code from the callback */
|
|
+ }
|
|
+ else {
|
|
+ PyErr_SetString(ErrorObject, "seek callback must return 0 (CURL_SEEKFUNC_OK), 1 (CURL_SEEKFUNC_FAIL), 2 (CURL_SEEKFUNC_CANTSEEK) or None");
|
|
+ goto verbose_error;
|
|
+ }
|
|
+
|
|
+silent_error:
|
|
+ Py_XDECREF(result);
|
|
+ PyEval_ReleaseThread(tmp_state);
|
|
+ return ret;
|
|
+verbose_error:
|
|
+ PyErr_Print();
|
|
+ goto silent_error;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
static size_t
|
|
read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
{
|
|
@@ -1988,7 +2066,8 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
const curl_progress_callback pro_cb = progress_callback;
|
|
const curl_debug_callback debug_cb = debug_callback;
|
|
const curl_ioctl_callback ioctl_cb = ioctl_callback;
|
|
- const curl_opensocket_callback opensocket_cb = opensocket_callback;
|
|
+ const curl_opensocket_callback opensocket_cb = opensocket_callback;
|
|
+ const curl_seek_callback seek_cb = seek_callback;
|
|
|
|
switch(option) {
|
|
case CURLOPT_WRITEFUNCTION:
|
|
@@ -2046,6 +2125,13 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
curl_easy_setopt(self->handle, CURLOPT_OPENSOCKETFUNCTION, opensocket_cb);
|
|
curl_easy_setopt(self->handle, CURLOPT_OPENSOCKETDATA, self);
|
|
break;
|
|
+ case CURLOPT_SEEKFUNCTION:
|
|
+ Py_INCREF(obj);
|
|
+ ZAP(self->seek_cb);
|
|
+ self->seek_cb = obj;
|
|
+ curl_easy_setopt(self->handle, CURLOPT_SEEKFUNCTION, seek_cb);
|
|
+ curl_easy_setopt(self->handle, CURLOPT_SEEKDATA, self);
|
|
+ break;
|
|
|
|
default:
|
|
/* None of the function options were recognized, throw exception */
|
|
@@ -3616,6 +3702,7 @@ initpycurl(void)
|
|
insint_c(d, "PREQUOTE", CURLOPT_PREQUOTE);
|
|
insint_c(d, "WRITEHEADER", CURLOPT_WRITEHEADER);
|
|
insint_c(d, "HEADERFUNCTION", CURLOPT_HEADERFUNCTION);
|
|
+ insint_c(d, "SEEKFUNCTION", CURLOPT_SEEKFUNCTION);
|
|
insint_c(d, "COOKIEFILE", CURLOPT_COOKIEFILE);
|
|
insint_c(d, "SSLVERSION", CURLOPT_SSLVERSION);
|
|
insint_c(d, "TIMECONDITION", CURLOPT_TIMECONDITION);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bd8a7fa3279613f41c503f5946d2576d4df70865 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Tue, 26 Feb 2013 09:13:24 +0100
|
|
Subject: [PATCH 009/149] pycurl.c: remove a left-over global variable introduced in r150
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 1 -
|
|
1 files changed, 0 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index ac448b0..094bc60 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -1529,7 +1529,6 @@ do_curl_reset(CurlObject *self)
|
|
}
|
|
|
|
/* --------------- unsetopt/setopt/getinfo --------------- */
|
|
- int res;
|
|
|
|
static PyObject *
|
|
util_curl_unsetopt(CurlObject *self, int option)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From de45f3fc04323c619a879e835f8f212c8c887364 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Mon, 25 Feb 2013 19:50:18 +0100
|
|
Subject: [PATCH 010/149] test_internals.py: add a test for ref-counting in reset()
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
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 a1a6533..3f5eefd 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
|
|
|
|
|
|
From be80a76e848ea77764da165d517ae0a8aca64604 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 01:15:00 -0500
|
|
Subject: [PATCH 011/149] Add gitignore
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.gitignore | 1 +
|
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
|
create mode 100644 .gitignore
|
|
|
|
diff --git a/.gitignore b/.gitignore
|
|
new file mode 100644
|
|
index 0000000..796b96d
|
|
--- /dev/null
|
|
+++ b/.gitignore
|
|
@@ -0,0 +1 @@
|
|
+/build
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c0bee23c728e61874fc2f89d800685c32b331f80 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 1 Mar 2013 00:11:47 -0500
|
|
Subject: [PATCH 012/149] A much simpler request test, in unittest format
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/request_test.py | 31 +++++++++++++++++++++++++++++++
|
|
1 files changed, 31 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/request_test.py
|
|
|
|
diff --git a/tests/request_test.py b/tests/request_test.py
|
|
new file mode 100644
|
|
index 0000000..0761d6c
|
|
--- /dev/null
|
|
+++ b/tests/request_test.py
|
|
@@ -0,0 +1,31 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+try:
|
|
+ from cStringIO import StringIO
|
|
+except ImportError:
|
|
+ try:
|
|
+ from StringIO import StringIO
|
|
+ except ImportError:
|
|
+ from io import StringIO
|
|
+
|
|
+class RequestTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_perform_get(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost')
|
|
+ self.curl.perform()
|
|
+
|
|
+ def test_perform_get_with_write_function(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost')
|
|
+ sio = StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+ print(sio.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c178c8f0b6ca9a839cd344b4ebe9e561d804d297 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 1 Mar 2013 13:35:59 -0500
|
|
Subject: [PATCH 013/149] init.py for test package
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
0 files changed, 0 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/__init__.py
|
|
|
|
diff --git a/tests/__init__.py b/tests/__init__.py
|
|
new file mode 100644
|
|
index 0000000..e69de29
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From a2a23e3e89e9d4cf7e61bf0259534fb0117ddf09 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 1 Mar 2013 13:36:08 -0500
|
|
Subject: [PATCH 014/149] wsgi application runner
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 82 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/runwsgi.py
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
new file mode 100644
|
|
index 0000000..d658614
|
|
--- /dev/null
|
|
+++ b/tests/runwsgi.py
|
|
@@ -0,0 +1,82 @@
|
|
+# Run a WSGI application in a daemon thread
|
|
+
|
|
+import bottle
|
|
+import threading
|
|
+import socket
|
|
+import time as _time
|
|
+
|
|
+class Server(bottle.WSGIRefServer):
|
|
+ def run(self, handler): # pragma: no cover
|
|
+ from wsgiref.simple_server import make_server, WSGIRequestHandler
|
|
+ if self.quiet:
|
|
+ base = self.options.get('handler_class', WSGIRequestHandler)
|
|
+ class QuietHandler(base):
|
|
+ def log_request(*args, **kw): pass
|
|
+ self.options['handler_class'] = QuietHandler
|
|
+ self.srv = make_server(self.host, self.port, handler, **self.options)
|
|
+ self.srv.serve_forever(poll_interval=0.1)
|
|
+
|
|
+def start_bottle_server(app, port, **kwargs):
|
|
+ server_thread = ServerThread(app, port, kwargs)
|
|
+ server_thread.daemon = True
|
|
+ server_thread.start()
|
|
+
|
|
+ ok = False
|
|
+ for i in range(10):
|
|
+ try:
|
|
+ conn = socket.create_connection(('127.0.0.1', port), 0.1)
|
|
+ except socket.error as e:
|
|
+ _time.sleep(0.1)
|
|
+ else:
|
|
+ conn.close()
|
|
+ ok = True
|
|
+ break
|
|
+ if not ok:
|
|
+ import warnings
|
|
+ warnings.warn('Server did not start after 1 second')
|
|
+
|
|
+ return server_thread.server
|
|
+
|
|
+class ServerThread(threading.Thread):
|
|
+ def __init__(self, app, port, server_kwargs):
|
|
+ threading.Thread.__init__(self)
|
|
+ self.app = app
|
|
+ self.port = port
|
|
+ self.server_kwargs = server_kwargs
|
|
+ self.server = Server(host='localhost', port=self.port, **self.server_kwargs)
|
|
+
|
|
+ def run(self):
|
|
+ bottle.run(self.app, server=self.server, quiet=True)
|
|
+
|
|
+def app_runner_setup(*specs):
|
|
+ '''Returns setup and teardown methods for running a list of WSGI
|
|
+ applications in a daemon thread.
|
|
+
|
|
+ Each argument is an (app, port) pair.
|
|
+
|
|
+ Return value is a (setup, teardown) function pair.
|
|
+
|
|
+ The setup and teardown functions expect to be called with an argument
|
|
+ on which server state will be stored.
|
|
+
|
|
+ Example usage with nose:
|
|
+
|
|
+ >>> setup_module, teardown_module = \
|
|
+ runwsgi.app_runner_setup((app_module.app, 8050))
|
|
+ '''
|
|
+
|
|
+ def setup(self):
|
|
+ self.servers = []
|
|
+ for spec in specs:
|
|
+ if len(spec) == 2:
|
|
+ app, port = spec
|
|
+ kwargs = {}
|
|
+ else:
|
|
+ app, port, kwargs = spec
|
|
+ self.servers.append(start_bottle_server(app, port, **kwargs))
|
|
+
|
|
+ def teardown(self):
|
|
+ for server in self.servers:
|
|
+ server.srv.shutdown()
|
|
+
|
|
+ return [setup, teardown]
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 72ac92b738b9709e84ebd56fd055286c173e5fee Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 1 Mar 2013 14:06:42 -0500
|
|
Subject: [PATCH 015/149] Test application to be on the server side
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/app.py | 7 +++++++
|
|
1 files changed, 7 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/app.py
|
|
|
|
diff --git a/tests/app.py b/tests/app.py
|
|
new file mode 100644
|
|
index 0000000..b173fd6
|
|
--- /dev/null
|
|
+++ b/tests/app.py
|
|
@@ -0,0 +1,7 @@
|
|
+import bottle
|
|
+
|
|
+app = bottle.Bottle()
|
|
+
|
|
+@app.route('/success')
|
|
+def ok():
|
|
+ return 'success'
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 83482f1c46d57074fa985def4f0aa62cc0df15d6 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 1 Mar 2013 14:07:04 -0500
|
|
Subject: [PATCH 016/149] Use the test application in request test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/request_test.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++--
|
|
1 files changed, 56 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/tests/request_test.py b/tests/request_test.py
|
|
index 0761d6c..127fbeb 100644
|
|
--- a/tests/request_test.py
|
|
+++ b/tests/request_test.py
|
|
@@ -2,8 +2,12 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
+import os
|
|
+import sys
|
|
+import tempfile
|
|
import pycurl
|
|
import unittest
|
|
+import io
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
@@ -12,6 +16,11 @@ except ImportError:
|
|
except ImportError:
|
|
from io import StringIO
|
|
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
class RequestTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.curl = pycurl.Curl()
|
|
@@ -20,12 +29,56 @@ class RequestTest(unittest.TestCase):
|
|
self.curl.close()
|
|
|
|
def test_perform_get(self):
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost')
|
|
+ # This test performs a GET request without doing anything else.
|
|
+ # Unfortunately, the default curl behavior is to print response
|
|
+ # body to standard output, which spams test output.
|
|
+ # As a result this test is commented out. Uncomment for debugging.
|
|
+ # test_perform_get_with_default_write_function is the test
|
|
+ # which exercises default curl write handler.
|
|
+ return
|
|
+
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
self.curl.perform()
|
|
|
|
def test_perform_get_with_write_function(self):
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost')
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
sio = StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.perform()
|
|
- print(sio.getvalue())
|
|
+ self.assertEqual('success', sio.getvalue())
|
|
+
|
|
+ def test_perform_get_with_default_write_function(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ #with tempfile.NamedTemporaryFile() as f:
|
|
+ with open('w', 'w+') as f:
|
|
+ # nose output capture plugin replaces sys.stdout with a StringIO
|
|
+ # instance. We want to redirect the underlying file descriptor
|
|
+ # anyway because underlying C code uses it.
|
|
+ # But keep track of whether we replace sys.stdout.
|
|
+ perform_dup = False
|
|
+ if hasattr(sys.stdout, 'fileno'):
|
|
+ try:
|
|
+ sys.stdout.fileno()
|
|
+ perform_dup = True
|
|
+ except io.UnsupportedOperation:
|
|
+ # stdout is a StringIO
|
|
+ pass
|
|
+ if perform_dup:
|
|
+ saved_stdout_fd = os.dup(sys.stdout.fileno())
|
|
+ os.dup2(f.fileno(), sys.stdout.fileno())
|
|
+ else:
|
|
+ saved_stdout = sys.stdout
|
|
+ sys.stdout = f
|
|
+ try:
|
|
+ self.curl.perform()
|
|
+ finally:
|
|
+ sys.stdout.flush()
|
|
+ if perform_dup:
|
|
+ os.fsync(sys.stdout.fileno())
|
|
+ os.dup2(saved_stdout_fd, sys.stdout.fileno())
|
|
+ os.close(saved_stdout_fd)
|
|
+ else:
|
|
+ sys.stdout = saved_stdout
|
|
+ f.seek(0)
|
|
+ body = f.read()
|
|
+ self.assertEqual('success', body)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 9f92a0e68c031e26012db508c2a9482f8a466f6c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sat, 2 Mar 2013 02:23:27 -0500
|
|
Subject: [PATCH 017/149] Put stringio import into util
|
|
|
|
This way all tests can simply import stringio from util in one line.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/util.py | 8 ++++++++
|
|
1 files changed, 8 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/util.py b/tests/util.py
|
|
index a1a9978..891da44 100644
|
|
--- a/tests/util.py
|
|
+++ b/tests/util.py
|
|
@@ -4,6 +4,14 @@
|
|
|
|
import os, sys
|
|
|
|
+try:
|
|
+ from cStringIO import StringIO
|
|
+except ImportError:
|
|
+ try:
|
|
+ from StringIO import StringIO
|
|
+ except ImportError:
|
|
+ from io import StringIO
|
|
+
|
|
#
|
|
# prepare sys.path in case we are still in the build directory
|
|
# see also: distutils/command/build.py (build_platlib)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 0289b4917a8510e174fe2237c28bdd219be3ef3f Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sat, 2 Mar 2013 02:24:11 -0500
|
|
Subject: [PATCH 018/149] Debug test, ported from the old debug test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/debug_test.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 46 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/debug_test.py
|
|
|
|
diff --git a/tests/debug_test.py b/tests/debug_test.py
|
|
new file mode 100644
|
|
index 0000000..dd00719
|
|
--- /dev/null
|
|
+++ b/tests/debug_test.py
|
|
@@ -0,0 +1,46 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class DebugTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+ self.debug_entries = []
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def debug_function(self, t, b):
|
|
+ self.debug_entries.append((t, b))
|
|
+
|
|
+ def test_perform_get_with_debug_function(self):
|
|
+ self.curl.setopt(pycurl.VERBOSE, 1)
|
|
+ self.curl.setopt(pycurl.DEBUGFUNCTION, self.debug_function)
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ self.curl.perform()
|
|
+
|
|
+ # Some checks with no particular intent
|
|
+ self.check(0, 'About to connect')
|
|
+ self.check(0, 'Connected to localhost')
|
|
+ self.check(0, 'port 8380')
|
|
+ # request
|
|
+ self.check(2, 'GET /success HTTP/1.1')
|
|
+ # response
|
|
+ self.check(1, 'HTTP/1.0 200 OK')
|
|
+ self.check(1, 'Content-Length: 7')
|
|
+ # result
|
|
+ self.check(3, 'success')
|
|
+
|
|
+ def check(self, wanted_t, wanted_b):
|
|
+ for t, b in self.debug_entries:
|
|
+ if t == wanted_t and wanted_b in b:
|
|
+ return
|
|
+ assert False, "%d: %s not found in debug entries" % (wanted_t, wanted_b)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 972cd4d7322aaa68074e44d5c9200a220fbb2b7e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sat, 2 Mar 2013 02:43:57 -0500
|
|
Subject: [PATCH 019/149] Write output to a stringio to avoid stdout spam
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/debug_test.py | 3 +++
|
|
1 files changed, 3 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/debug_test.py b/tests/debug_test.py
|
|
index dd00719..8005239 100644
|
|
--- a/tests/debug_test.py
|
|
+++ b/tests/debug_test.py
|
|
@@ -7,6 +7,7 @@ import unittest
|
|
|
|
from . import app
|
|
from . import runwsgi
|
|
+from . import util
|
|
|
|
setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
@@ -25,6 +26,8 @@ class DebugTest(unittest.TestCase):
|
|
self.curl.setopt(pycurl.VERBOSE, 1)
|
|
self.curl.setopt(pycurl.DEBUGFUNCTION, self.debug_function)
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.perform()
|
|
|
|
# Some checks with no particular intent
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From ece77e7257bea16a9a9d4dd5efd948358974bc4a Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sat, 2 Mar 2013 02:44:24 -0500
|
|
Subject: [PATCH 020/149] Use stringio from util in request test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/request_test.py | 10 ++--------
|
|
1 files changed, 2 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/tests/request_test.py b/tests/request_test.py
|
|
index 127fbeb..afd8566 100644
|
|
--- a/tests/request_test.py
|
|
+++ b/tests/request_test.py
|
|
@@ -8,16 +8,10 @@ import tempfile
|
|
import pycurl
|
|
import unittest
|
|
import io
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- try:
|
|
- from StringIO import StringIO
|
|
- except ImportError:
|
|
- from io import StringIO
|
|
|
|
from . import app
|
|
from . import runwsgi
|
|
+from . import util
|
|
|
|
setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
@@ -42,7 +36,7 @@ class RequestTest(unittest.TestCase):
|
|
|
|
def test_perform_get_with_write_function(self):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
- sio = StringIO()
|
|
+ sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.perform()
|
|
self.assertEqual('success', sio.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From aa359d2da90735e06d9c5dcf387e472e4b11f60d Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sat, 2 Mar 2013 04:06:00 -0500
|
|
Subject: [PATCH 021/149] Add a test that writes response to a file
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/request_test.py | 9 +++++++++
|
|
1 files changed, 9 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/request_test.py b/tests/request_test.py
|
|
index afd8566..7386a51 100644
|
|
--- a/tests/request_test.py
|
|
+++ b/tests/request_test.py
|
|
@@ -41,6 +41,15 @@ class RequestTest(unittest.TestCase):
|
|
self.curl.perform()
|
|
self.assertEqual('success', sio.getvalue())
|
|
|
|
+ def test_write_to_file(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ with tempfile.NamedTemporaryFile() as f:
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, f.write)
|
|
+ self.curl.perform()
|
|
+ f.seek(0)
|
|
+ body = f.read()
|
|
+ self.assertEqual('success', body)
|
|
+
|
|
def test_perform_get_with_default_write_function(self):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
#with tempfile.NamedTemporaryFile() as f:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 517c8f2dd4dc519fd733e049abab704e052866b6 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:14:26 -0500
|
|
Subject: [PATCH 022/149] Account for the case of nose running no tests
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 4 +++-
|
|
1 files changed, 3 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index d658614..7b39358 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -77,6 +77,8 @@ def app_runner_setup(*specs):
|
|
|
|
def teardown(self):
|
|
for server in self.servers:
|
|
- server.srv.shutdown()
|
|
+ # if no tests from module were run, there is no server to shut down
|
|
+ if hasattr(server, 'srv'):
|
|
+ server.srv.shutdown()
|
|
|
|
return [setup, teardown]
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From cc68fffc8365c4f8e761a586d5e74beb5fd71473 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:14:41 -0500
|
|
Subject: [PATCH 023/149] Split request test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 70 +++++++++++++++++++++++++++
|
|
tests/request_test.py | 87 ----------------------------------
|
|
tests/write_to_file_test.py | 29 +++++++++++
|
|
tests/write_to_stringio_test.py | 30 ++++++++++++
|
|
4 files changed, 129 insertions(+), 87 deletions(-)
|
|
create mode 100644 tests/default_write_function_test.py
|
|
delete mode 100644 tests/request_test.py
|
|
create mode 100644 tests/write_to_file_test.py
|
|
create mode 100644 tests/write_to_stringio_test.py
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
new file mode 100644
|
|
index 0000000..2efc579
|
|
--- /dev/null
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -0,0 +1,70 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import unittest
|
|
+import pycurl
|
|
+import sys
|
|
+import tempfile
|
|
+import io
|
|
+import os
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class RequestTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_perform_get(self):
|
|
+ # This test performs a GET request without doing anything else.
|
|
+ # Unfortunately, the default curl behavior is to print response
|
|
+ # body to standard output, which spams test output.
|
|
+ # As a result this test is commented out. Uncomment for debugging.
|
|
+ # test_perform_get_with_default_write_function is the test
|
|
+ # which exercises default curl write handler.
|
|
+
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ self.curl.perform()
|
|
+
|
|
+ def test_perform_get_with_default_write_function(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ #with tempfile.NamedTemporaryFile() as f:
|
|
+ with open('w', 'w+') as f:
|
|
+ # nose output capture plugin replaces sys.stdout with a StringIO
|
|
+ # instance. We want to redirect the underlying file descriptor
|
|
+ # anyway because underlying C code uses it.
|
|
+ # But keep track of whether we replace sys.stdout.
|
|
+ perform_dup = False
|
|
+ if hasattr(sys.stdout, 'fileno'):
|
|
+ try:
|
|
+ sys.stdout.fileno()
|
|
+ perform_dup = True
|
|
+ except io.UnsupportedOperation:
|
|
+ # stdout is a StringIO
|
|
+ pass
|
|
+ if perform_dup:
|
|
+ saved_stdout_fd = os.dup(sys.stdout.fileno())
|
|
+ os.dup2(f.fileno(), sys.stdout.fileno())
|
|
+ else:
|
|
+ saved_stdout = sys.stdout
|
|
+ sys.stdout = f
|
|
+ try:
|
|
+ self.curl.perform()
|
|
+ finally:
|
|
+ sys.stdout.flush()
|
|
+ if perform_dup:
|
|
+ os.fsync(sys.stdout.fileno())
|
|
+ os.dup2(saved_stdout_fd, sys.stdout.fileno())
|
|
+ os.close(saved_stdout_fd)
|
|
+ else:
|
|
+ sys.stdout = saved_stdout
|
|
+ f.seek(0)
|
|
+ body = f.read()
|
|
+ self.assertEqual('success', body)
|
|
diff --git a/tests/request_test.py b/tests/request_test.py
|
|
deleted file mode 100644
|
|
index 7386a51..0000000
|
|
--- a/tests/request_test.py
|
|
+++ /dev/null
|
|
@@ -1,87 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-
|
|
-import os
|
|
-import sys
|
|
-import tempfile
|
|
-import pycurl
|
|
-import unittest
|
|
-import io
|
|
-
|
|
-from . import app
|
|
-from . import runwsgi
|
|
-from . import util
|
|
-
|
|
-setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
-
|
|
-class RequestTest(unittest.TestCase):
|
|
- def setUp(self):
|
|
- self.curl = pycurl.Curl()
|
|
-
|
|
- def tearDown(self):
|
|
- self.curl.close()
|
|
-
|
|
- def test_perform_get(self):
|
|
- # This test performs a GET request without doing anything else.
|
|
- # Unfortunately, the default curl behavior is to print response
|
|
- # body to standard output, which spams test output.
|
|
- # As a result this test is commented out. Uncomment for debugging.
|
|
- # test_perform_get_with_default_write_function is the test
|
|
- # which exercises default curl write handler.
|
|
- return
|
|
-
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
- self.curl.perform()
|
|
-
|
|
- def test_perform_get_with_write_function(self):
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
- sio = util.StringIO()
|
|
- self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
- self.curl.perform()
|
|
- self.assertEqual('success', sio.getvalue())
|
|
-
|
|
- def test_write_to_file(self):
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
- with tempfile.NamedTemporaryFile() as f:
|
|
- self.curl.setopt(pycurl.WRITEFUNCTION, f.write)
|
|
- self.curl.perform()
|
|
- f.seek(0)
|
|
- body = f.read()
|
|
- self.assertEqual('success', body)
|
|
-
|
|
- def test_perform_get_with_default_write_function(self):
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
- #with tempfile.NamedTemporaryFile() as f:
|
|
- with open('w', 'w+') as f:
|
|
- # nose output capture plugin replaces sys.stdout with a StringIO
|
|
- # instance. We want to redirect the underlying file descriptor
|
|
- # anyway because underlying C code uses it.
|
|
- # But keep track of whether we replace sys.stdout.
|
|
- perform_dup = False
|
|
- if hasattr(sys.stdout, 'fileno'):
|
|
- try:
|
|
- sys.stdout.fileno()
|
|
- perform_dup = True
|
|
- except io.UnsupportedOperation:
|
|
- # stdout is a StringIO
|
|
- pass
|
|
- if perform_dup:
|
|
- saved_stdout_fd = os.dup(sys.stdout.fileno())
|
|
- os.dup2(f.fileno(), sys.stdout.fileno())
|
|
- else:
|
|
- saved_stdout = sys.stdout
|
|
- sys.stdout = f
|
|
- try:
|
|
- self.curl.perform()
|
|
- finally:
|
|
- sys.stdout.flush()
|
|
- if perform_dup:
|
|
- os.fsync(sys.stdout.fileno())
|
|
- os.dup2(saved_stdout_fd, sys.stdout.fileno())
|
|
- os.close(saved_stdout_fd)
|
|
- else:
|
|
- sys.stdout = saved_stdout
|
|
- f.seek(0)
|
|
- body = f.read()
|
|
- self.assertEqual('success', body)
|
|
diff --git a/tests/write_to_file_test.py b/tests/write_to_file_test.py
|
|
new file mode 100644
|
|
index 0000000..6528f81
|
|
--- /dev/null
|
|
+++ b/tests/write_to_file_test.py
|
|
@@ -0,0 +1,29 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import unittest
|
|
+import pycurl
|
|
+import tempfile
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class RequestTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_get_to_file(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ with tempfile.NamedTemporaryFile() as f:
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, f.write)
|
|
+ self.curl.perform()
|
|
+ f.seek(0)
|
|
+ body = f.read()
|
|
+ self.assertEqual('success', body)
|
|
diff --git a/tests/write_to_stringio_test.py b/tests/write_to_stringio_test.py
|
|
new file mode 100644
|
|
index 0000000..fd1c28d
|
|
--- /dev/null
|
|
+++ b/tests/write_to_stringio_test.py
|
|
@@ -0,0 +1,30 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import os
|
|
+import sys
|
|
+import tempfile
|
|
+import pycurl
|
|
+import unittest
|
|
+import io
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class WriteToStringioTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_get(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+ self.assertEqual('success', sio.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From f7055358a57d0fa9bcef3f0ad38a63ff5422178c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:22:05 -0500
|
|
Subject: [PATCH 024/149] Need to flush when using default write function
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 5 ++++-
|
|
1 files changed, 4 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index 2efc579..afbba33 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -32,6 +32,9 @@ class RequestTest(unittest.TestCase):
|
|
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
self.curl.perform()
|
|
+ # If this flush is not done, stdout output bleeds into the next test
|
|
+ # that is executed
|
|
+ sys.stdout.flush()
|
|
|
|
def test_perform_get_with_default_write_function(self):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
@@ -57,8 +60,8 @@ class RequestTest(unittest.TestCase):
|
|
sys.stdout = f
|
|
try:
|
|
self.curl.perform()
|
|
- finally:
|
|
sys.stdout.flush()
|
|
+ finally:
|
|
if perform_dup:
|
|
os.fsync(sys.stdout.fileno())
|
|
os.dup2(saved_stdout_fd, sys.stdout.fileno())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bb6edcd11b75949aa4c7b7513ce70f8a16a8a857 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:34:39 -0500
|
|
Subject: [PATCH 025/149] Trying to get the default write function test to work with nose output capture, but no luck so far
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 52 +++++++++++++++++----------------
|
|
1 files changed, 27 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index afbba33..853992b 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -15,6 +15,8 @@ from . import util
|
|
|
|
setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
+STDOUT_FD_NUM = 1
|
|
+
|
|
class RequestTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.curl = pycurl.Curl()
|
|
@@ -33,41 +35,41 @@ class RequestTest(unittest.TestCase):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
self.curl.perform()
|
|
# If this flush is not done, stdout output bleeds into the next test
|
|
- # that is executed
|
|
+ # that is executed (without nose output capture)
|
|
sys.stdout.flush()
|
|
+ os.fsync(STDOUT_FD_NUM)
|
|
|
|
- def test_perform_get_with_default_write_function(self):
|
|
+ # I have a really hard time getting this to work with nose output capture
|
|
+ def skip_test_perform_get_with_default_write_function(self):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
- #with tempfile.NamedTemporaryFile() as f:
|
|
- with open('w', 'w+') as f:
|
|
+ with tempfile.NamedTemporaryFile() as f:
|
|
+ #with open('w', 'w+') as f:
|
|
# nose output capture plugin replaces sys.stdout with a StringIO
|
|
# instance. We want to redirect the underlying file descriptor
|
|
# anyway because underlying C code uses it.
|
|
- # But keep track of whether we replace sys.stdout.
|
|
- perform_dup = False
|
|
- if hasattr(sys.stdout, 'fileno'):
|
|
- try:
|
|
- sys.stdout.fileno()
|
|
- perform_dup = True
|
|
- except io.UnsupportedOperation:
|
|
- # stdout is a StringIO
|
|
- pass
|
|
- if perform_dup:
|
|
- saved_stdout_fd = os.dup(sys.stdout.fileno())
|
|
- os.dup2(f.fileno(), sys.stdout.fileno())
|
|
- else:
|
|
- saved_stdout = sys.stdout
|
|
- sys.stdout = f
|
|
+ # Therefore:
|
|
+ # 1. Use file descriptor 1 rather than sys.stdout.fileno() to
|
|
+ # reference the standard output file descriptor.
|
|
+ # 2. We do not touch sys.stdout. This means anything written to
|
|
+ # sys.stdout will be captured by nose, and not make it to our code.
|
|
+ # But the output we care about happens at libcurl level, below
|
|
+ # nose, therefore this is fine.
|
|
+ saved_stdout_fd = os.dup(STDOUT_FD_NUM)
|
|
+ os.dup2(f.fileno(), STDOUT_FD_NUM)
|
|
+ #os.dup2(1, 100)
|
|
+ #os.dup2(2, 1)
|
|
+ # We also need to flush the output that libcurl wrote to stdout.
|
|
+ # Since sys.stdout might be nose's StringIO instance, open the
|
|
+ # stdout file descriptor manually.
|
|
+
|
|
try:
|
|
self.curl.perform()
|
|
sys.stdout.flush()
|
|
finally:
|
|
- if perform_dup:
|
|
- os.fsync(sys.stdout.fileno())
|
|
- os.dup2(saved_stdout_fd, sys.stdout.fileno())
|
|
- os.close(saved_stdout_fd)
|
|
- else:
|
|
- sys.stdout = saved_stdout
|
|
+ os.fsync(STDOUT_FD_NUM)
|
|
+ os.dup2(saved_stdout_fd, STDOUT_FD_NUM)
|
|
+ os.close(saved_stdout_fd)
|
|
+ #os.dup2(100, 1)
|
|
f.seek(0)
|
|
body = f.read()
|
|
self.assertEqual('success', body)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 83a7d49e7e27f499e9d400a1af09e07fcc595c2f Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:35:25 -0500
|
|
Subject: [PATCH 026/149] Fix test class names
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 2 +-
|
|
tests/write_to_file_test.py | 2 +-
|
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index 853992b..a0de66e 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -17,7 +17,7 @@ setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
STDOUT_FD_NUM = 1
|
|
|
|
-class RequestTest(unittest.TestCase):
|
|
+class DefaultWriteFunctionTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.curl = pycurl.Curl()
|
|
|
|
diff --git a/tests/write_to_file_test.py b/tests/write_to_file_test.py
|
|
index 6528f81..67c9c63 100644
|
|
--- a/tests/write_to_file_test.py
|
|
+++ b/tests/write_to_file_test.py
|
|
@@ -12,7 +12,7 @@ from . import util
|
|
|
|
setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
-class RequestTest(unittest.TestCase):
|
|
+class WriteToFileTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.curl = pycurl.Curl()
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 44ff45d8644789a098ea68b196b5f5cea5fbfd35 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:36:34 -0500
|
|
Subject: [PATCH 027/149] Delete unused imports
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/write_to_stringio_test.py | 3 ---
|
|
1 files changed, 0 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/tests/write_to_stringio_test.py b/tests/write_to_stringio_test.py
|
|
index fd1c28d..018800d 100644
|
|
--- a/tests/write_to_stringio_test.py
|
|
+++ b/tests/write_to_stringio_test.py
|
|
@@ -2,9 +2,6 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
-import os
|
|
-import sys
|
|
-import tempfile
|
|
import pycurl
|
|
import unittest
|
|
import io
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From f14cdea639d6976f8dd8077be28c4452d4c8d1cf Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 00:41:35 -0500
|
|
Subject: [PATCH 028/149] Test for header function
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/header_function_test.py | 50 +++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 50 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/header_function_test.py
|
|
|
|
diff --git a/tests/header_function_test.py b/tests/header_function_test.py
|
|
new file mode 100644
|
|
index 0000000..bfe7173
|
|
--- /dev/null
|
|
+++ b/tests/header_function_test.py
|
|
@@ -0,0 +1,50 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import io
|
|
+import time as _time
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class HeaderFunctionTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+ self.header_lines = []
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def header_function(self, line):
|
|
+ self.header_lines.append(line)
|
|
+
|
|
+ def test_get(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.setopt(pycurl.HEADERFUNCTION, self.header_function)
|
|
+ self.curl.perform()
|
|
+ self.assertEqual('success', sio.getvalue())
|
|
+
|
|
+ assert len(self.header_lines) > 0
|
|
+ self.assertEqual("HTTP/1.0 200 OK\r\n", self.header_lines[0])
|
|
+ # day of week
|
|
+ todays_day = _time.strftime('%a')
|
|
+ # Date: Sun, 03 Mar 2013 05:38:12 GMT\r\n
|
|
+ self.check('Date: %s' % todays_day)
|
|
+ # Server: WSGIServer/0.1 Python/2.7.3\r\n
|
|
+ self.check('Server: WSGIServer')
|
|
+ self.check('Content-Length: 7')
|
|
+ self.check('Content-Type: text/html')
|
|
+
|
|
+ def check(self, wanted_text):
|
|
+ for line in self.header_lines:
|
|
+ if wanted_text in line:
|
|
+ return
|
|
+ assert False, "%s not found in header lines" % wanted_text
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2491ddd3f028059b4e86338ad64413de75db28af Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 01:35:21 -0500
|
|
Subject: [PATCH 029/149] FTP test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/ftp_test.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 48 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/ftp_test.py
|
|
|
|
diff --git a/tests/ftp_test.py b/tests/ftp_test.py
|
|
new file mode 100644
|
|
index 0000000..d215b6e
|
|
--- /dev/null
|
|
+++ b/tests/ftp_test.py
|
|
@@ -0,0 +1,48 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+
|
|
+from . import util
|
|
+
|
|
+class FtpTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_get_ftp(self):
|
|
+ self.curl.setopt(pycurl.URL, 'ftp://localhost:8921')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+
|
|
+ result = sio.getvalue()
|
|
+ assert 'README' in result
|
|
+ assert 'bin -> usr/bin' in result
|
|
+
|
|
+ # XXX this test needs to be fixed
|
|
+ def test_quote(self):
|
|
+ self.curl.setopt(pycurl.URL, 'ftp://localhost:8921')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.setopt(pycurl.QUOTE, ['CWD pub'])
|
|
+ self.curl.perform()
|
|
+
|
|
+ result = sio.getvalue()
|
|
+ assert 'README' in result
|
|
+ assert 'bin -> usr/bin' in result
|
|
+
|
|
+ def test_epsv(self):
|
|
+ self.curl.setopt(pycurl.URL, 'ftp://localhost:8921')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.setopt(pycurl.FTP_USE_EPSV, 1)
|
|
+ self.curl.perform()
|
|
+
|
|
+ result = sio.getvalue()
|
|
+ assert 'README' in result
|
|
+ assert 'bin -> usr/bin' in result
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From ead7f2743a7bd6b497d994ca11dc823a144d50d7 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 01:44:22 -0500
|
|
Subject: [PATCH 030/149] Getinfo test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/getinfo_test.py | 43 +++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 43 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/getinfo_test.py
|
|
|
|
diff --git a/tests/getinfo_test.py b/tests/getinfo_test.py
|
|
new file mode 100644
|
|
index 0000000..39dff2f
|
|
--- /dev/null
|
|
+++ b/tests/getinfo_test.py
|
|
@@ -0,0 +1,43 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class GetinfoTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_getinfo(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+ self.assertEqual('success', sio.getvalue())
|
|
+
|
|
+ self.assertEqual(200, self.curl.getinfo(pycurl.HTTP_CODE))
|
|
+ assert type(self.curl.getinfo(pycurl.TOTAL_TIME)) is float
|
|
+ assert self.curl.getinfo(pycurl.TOTAL_TIME) > 0
|
|
+ assert self.curl.getinfo(pycurl.TOTAL_TIME) < 1
|
|
+ assert type(self.curl.getinfo(pycurl.SPEED_DOWNLOAD)) is float
|
|
+ assert self.curl.getinfo(pycurl.SPEED_DOWNLOAD) > 0
|
|
+ self.assertEqual(7, self.curl.getinfo(pycurl.SIZE_DOWNLOAD))
|
|
+ self.assertEqual('http://localhost:8380/success', self.curl.getinfo(pycurl.EFFECTIVE_URL))
|
|
+ self.assertEqual('text/html; charset=utf-8', self.curl.getinfo(pycurl.CONTENT_TYPE).lower())
|
|
+ assert type(self.curl.getinfo(pycurl.NAMELOOKUP_TIME)) is float
|
|
+ assert self.curl.getinfo(pycurl.NAMELOOKUP_TIME) > 0
|
|
+ assert self.curl.getinfo(pycurl.NAMELOOKUP_TIME) < 1
|
|
+ self.assertEqual(0, self.curl.getinfo(pycurl.REDIRECT_TIME))
|
|
+ self.assertEqual(0, self.curl.getinfo(pycurl.REDIRECT_COUNT))
|
|
+ # time not requested
|
|
+ self.assertEqual(-1, self.curl.getinfo(pycurl.INFO_FILETIME))
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 7c48535bef19bf13a9d8aef377d4465490a588f2 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 02:05:30 -0500
|
|
Subject: [PATCH 031/149] Ported internals test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/internals_test.py | 224 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 224 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/internals_test.py
|
|
|
|
diff --git a/tests/internals_test.py b/tests/internals_test.py
|
|
new file mode 100644
|
|
index 0000000..34d4eb8
|
|
--- /dev/null
|
|
+++ b/tests/internals_test.py
|
|
@@ -0,0 +1,224 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+from .util import StringIO
|
|
+try:
|
|
+ import cPickle
|
|
+except ImportError:
|
|
+ cPickle = None
|
|
+import pickle
|
|
+import gc
|
|
+import copy
|
|
+
|
|
+class InternalsTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+ del self.curl
|
|
+
|
|
+ # /***********************************************************************
|
|
+ # // test misc
|
|
+ # ************************************************************************/
|
|
+
|
|
+ def test_constant_aliasing(self):
|
|
+ assert self.curl.URL is pycurl.URL
|
|
+
|
|
+ # /***********************************************************************
|
|
+ # // test handles
|
|
+ # ************************************************************************/
|
|
+
|
|
+ def test_remove_invalid_handle(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ try:
|
|
+ m.remove_handle(self.curl)
|
|
+ except pycurl.error:
|
|
+ pass
|
|
+ else:
|
|
+ assert False, "No exception when trying to remove a handle that is not in CurlMulti"
|
|
+ del m
|
|
+
|
|
+ def test_remove_invalid_closed_handle(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ c = pycurl.Curl()
|
|
+ c.close()
|
|
+ m.remove_handle(c)
|
|
+ del m, c
|
|
+
|
|
+ def test_add_closed_handle(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ c = pycurl.Curl()
|
|
+ c.close()
|
|
+ try:
|
|
+ m.add_handle(c)
|
|
+ except pycurl.error:
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to add a close handle to CurlMulti"
|
|
+ m.close()
|
|
+ del m, c
|
|
+
|
|
+ def test_add_handle_twice(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.add_handle(self.curl)
|
|
+ try:
|
|
+ m.add_handle(self.curl)
|
|
+ except pycurl.error:
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to add the same handle twice"
|
|
+ del m
|
|
+
|
|
+ def test_add_handle_on_multiple_stacks(self):
|
|
+ m1 = pycurl.CurlMulti()
|
|
+ m2 = pycurl.CurlMulti()
|
|
+ m1.add_handle(self.curl)
|
|
+ try:
|
|
+ m2.add_handle(self.curl)
|
|
+ except pycurl.error:
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to add the same handle on multiple stacks"
|
|
+ del m1, m2
|
|
+
|
|
+ def test_move_handle(self):
|
|
+ m1 = pycurl.CurlMulti()
|
|
+ m2 = pycurl.CurlMulti()
|
|
+ m1.add_handle(self.curl)
|
|
+ m1.remove_handle(self.curl)
|
|
+ m2.add_handle(self.curl)
|
|
+ del m1, m2
|
|
+
|
|
+ # /***********************************************************************
|
|
+ # // test copying and pickling - copying and pickling of
|
|
+ # // instances of Curl and CurlMulti is not allowed
|
|
+ # ************************************************************************/
|
|
+
|
|
+ def test_copy_curl(self):
|
|
+ try:
|
|
+ copy.copy(self.curl)
|
|
+ # python 2 raises copy.Error, python 3 raises TypeError
|
|
+ except (copy.Error, TypeError):
|
|
+ pass
|
|
+ else:
|
|
+ assert False, "No exception when trying to copy a Curl handle"
|
|
+
|
|
+ def test_copy_multi(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ try:
|
|
+ copy.copy(m)
|
|
+ except (copy.Error, TypeError):
|
|
+ pass
|
|
+ else:
|
|
+ assert False, "No exception when trying to copy a CurlMulti handle"
|
|
+
|
|
+ def test_pickle_curl(self):
|
|
+ fp = StringIO()
|
|
+ p = pickle.Pickler(fp, 1)
|
|
+ try:
|
|
+ p.dump(self.curl)
|
|
+ # python 2 raises pickle.PicklingError, python 3 raises TypeError
|
|
+ except (pickle.PicklingError, TypeError):
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to pickle a Curl handle"
|
|
+ del fp, p
|
|
+
|
|
+ def test_pickle_multi(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ fp = StringIO()
|
|
+ p = pickle.Pickler(fp, 1)
|
|
+ try:
|
|
+ p.dump(m)
|
|
+ except (pickle.PicklingError, TypeError):
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to pickle a CurlMulti handle"
|
|
+ del m, fp, p
|
|
+
|
|
+ if cPickle is not None:
|
|
+ def test_cpickle_curl(self):
|
|
+ fp = StringIO()
|
|
+ p = cPickle.Pickler(fp, 1)
|
|
+ try:
|
|
+ p.dump(self.curl)
|
|
+ except cPickle.PicklingError:
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to pickle a Curl handle via cPickle"
|
|
+ del fp, p
|
|
+
|
|
+ def test_cpickle_multi(self):
|
|
+ m = pycurl.CurlMulti()
|
|
+ fp = StringIO()
|
|
+ p = cPickle.Pickler(fp, 1)
|
|
+ try:
|
|
+ p.dump(m)
|
|
+ except cPickle.PicklingError:
|
|
+ pass
|
|
+ else:
|
|
+ assert 0, "No exception when trying to pickle a CurlMulti handle via cPickle"
|
|
+ del m, fp, p
|
|
+
|
|
+ # /***********************************************************************
|
|
+ # // test refcounts
|
|
+ # ************************************************************************/
|
|
+
|
|
+ # basic check of reference counting (use a memory checker like valgrind)
|
|
+ def test_reference_counting(self):
|
|
+ c = pycurl.Curl()
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.add_handle(c)
|
|
+ del m
|
|
+ m = pycurl.CurlMulti()
|
|
+ c.close()
|
|
+ del m, c
|
|
+
|
|
+ def test_cyclic_gc(self):
|
|
+ gc.collect()
|
|
+ c = pycurl.Curl()
|
|
+ c.m = pycurl.CurlMulti()
|
|
+ c.m.add_handle(c)
|
|
+ # create some nasty cyclic references
|
|
+ c.c = c
|
|
+ c.c.c1 = c
|
|
+ c.c.c2 = c
|
|
+ c.c.c3 = c.c
|
|
+ c.c.c4 = c.m
|
|
+ c.m.c = c
|
|
+ c.m.m = c.m
|
|
+ c.m.c = c
|
|
+ # delete
|
|
+ gc.collect()
|
|
+ flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE
|
|
+ # python 3 has no DEBUG_OBJECTS
|
|
+ #if hasattr(gc, 'DEBUG_OBJECTS'):
|
|
+ #flags |= gc.DEBUG_OBJECTS
|
|
+ #if opts.verbose >= 1:
|
|
+ #flags = flags | gc.DEBUG_STATS
|
|
+ gc.set_debug(flags)
|
|
+ gc.collect()
|
|
+ ##print gc.get_referrers(c)
|
|
+ ##print gc.get_objects()
|
|
+ #if opts.verbose >= 1:
|
|
+ #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()))
|
|
+
|
|
+ def test_refcounting_bug_in_reset(self):
|
|
+ try:
|
|
+ range_generator = xrange
|
|
+ except NameError:
|
|
+ range_generator = range
|
|
+ # Ensure that the refcounting error in "reset" is fixed:
|
|
+ for i in range_generator(100000):
|
|
+ c = pycurl.Curl()
|
|
+ c.reset()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c7b8f39437e953deb8af1b17f366a6242db28d5d Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 02:16:10 -0500
|
|
Subject: [PATCH 032/149] Make cyclic gc test actually check that cycles are collected
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/internals_test.py | 9 +++++++++
|
|
1 files changed, 9 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/internals_test.py b/tests/internals_test.py
|
|
index 34d4eb8..fb451df 100644
|
|
--- a/tests/internals_test.py
|
|
+++ b/tests/internals_test.py
|
|
@@ -12,6 +12,7 @@ except ImportError:
|
|
import pickle
|
|
import gc
|
|
import copy
|
|
+import re
|
|
|
|
class InternalsTest(unittest.TestCase):
|
|
def setUp(self):
|
|
@@ -179,6 +180,7 @@ class InternalsTest(unittest.TestCase):
|
|
del m, c
|
|
|
|
def test_cyclic_gc(self):
|
|
+ regexp = re.compile(r'at (0x\d+)')
|
|
gc.collect()
|
|
c = pycurl.Curl()
|
|
c.m = pycurl.CurlMulti()
|
|
@@ -206,10 +208,17 @@ class InternalsTest(unittest.TestCase):
|
|
##print gc.get_objects()
|
|
#if opts.verbose >= 1:
|
|
#print("Tracked objects:", len(gc.get_objects()))
|
|
+ match = regexp.search(repr(c))
|
|
+ assert match is not None
|
|
+ address = match.group(1)
|
|
# The `del' below should delete these 4 objects:
|
|
# Curl + internal dict, CurlMulti + internal dict
|
|
del c
|
|
gc.collect()
|
|
+ objects = gc.get_objects()
|
|
+ search = 'at %s' % address
|
|
+ for object in objects:
|
|
+ assert search not in repr(object)
|
|
#if opts.verbose >= 1:
|
|
#print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 6fa36d3a070e784fc679427a6c56725ee30375e8 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 03:00:20 -0500
|
|
Subject: [PATCH 033/149] Ported memleak test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/memleak_test.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 59 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/memleak_test.py
|
|
|
|
diff --git a/tests/memleak_test.py b/tests/memleak_test.py
|
|
new file mode 100644
|
|
index 0000000..6e9f76c
|
|
--- /dev/null
|
|
+++ b/tests/memleak_test.py
|
|
@@ -0,0 +1,59 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import gc
|
|
+import re
|
|
+
|
|
+class MemleakTest(unittest.TestCase):
|
|
+ def test_collection(self):
|
|
+ regexp = re.compile(r'at (0x\d+)')
|
|
+
|
|
+ gc.collect()
|
|
+ flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE
|
|
+ # python 3 has no DEBUG_OBJECTS
|
|
+ #if hasattr(gc, 'DEBUG_OBJECTS'):
|
|
+ #flags |= gc.DEBUG_OBJECTS
|
|
+ #if 1:
|
|
+ #flags = flags | gc.DEBUG_STATS
|
|
+ #gc.set_debug(flags)
|
|
+ gc.collect()
|
|
+
|
|
+ #print("Tracked objects:", len(gc.get_objects()))
|
|
+
|
|
+ multi = pycurl.CurlMulti()
|
|
+ t = []
|
|
+ searches = []
|
|
+ for a in range(100):
|
|
+ curl = pycurl.Curl()
|
|
+ multi.add_handle(curl)
|
|
+ t.append(curl)
|
|
+
|
|
+ match = regexp.search(repr(curl))
|
|
+ assert match is not None
|
|
+ searches.append(match.group(1))
|
|
+ match = regexp.search(repr(multi))
|
|
+ assert match
|
|
+ searches.append(match.group(1))
|
|
+
|
|
+ #print("Tracked objects:", len(gc.get_objects()))
|
|
+
|
|
+ for curl in t:
|
|
+ curl.close()
|
|
+ multi.remove_handle(curl)
|
|
+
|
|
+ #print("Tracked objects:", len(gc.get_objects()))
|
|
+
|
|
+ del curl
|
|
+ del t
|
|
+ del multi
|
|
+
|
|
+ #print("Tracked objects:", len(gc.get_objects()))
|
|
+ gc.collect()
|
|
+ #print("Tracked objects:", len(gc.get_objects()))
|
|
+
|
|
+ objects = gc.get_objects()
|
|
+ for search in searches:
|
|
+ assert 'at %s' % search not in repr(object)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From cef807dfde5e1ca931947ec37d0171227899e72f Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 03:06:26 -0500
|
|
Subject: [PATCH 034/149] Ported the first multi test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 56 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/multi_test.py
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
new file mode 100644
|
|
index 0000000..4c0bdaf
|
|
--- /dev/null
|
|
+++ b/tests/multi_test.py
|
|
@@ -0,0 +1,56 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module_1, teardown_module_1 = runwsgi.app_runner_setup((app.app, 8380))
|
|
+setup_module_2, teardown_module_2 = runwsgi.app_runner_setup((app.app, 8381))
|
|
+
|
|
+def setup_module(mod):
|
|
+ setup_module_1(mod)
|
|
+ setup_module_2(mod)
|
|
+
|
|
+def teardown_module(mod):
|
|
+ teardown_module_2(mod)
|
|
+ teardown_module_1(mod)
|
|
+
|
|
+class MultiTest(unittest.TestCase):
|
|
+ def test_multi(self):
|
|
+ io1 = util.StringIO()
|
|
+ io2 = util.StringIO()
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.handles = []
|
|
+ c1 = pycurl.Curl()
|
|
+ c2 = pycurl.Curl()
|
|
+ c1.setopt(c1.URL, 'http://localhost:8380/success')
|
|
+ c1.setopt(c1.WRITEFUNCTION, io1.write)
|
|
+ c2.setopt(c2.URL, 'http://localhost:8381/success')
|
|
+ c2.setopt(c1.WRITEFUNCTION, io2.write)
|
|
+ m.add_handle(c1)
|
|
+ m.add_handle(c2)
|
|
+ m.handles.append(c1)
|
|
+ m.handles.append(c2)
|
|
+
|
|
+ num_handles = len(m.handles)
|
|
+ while num_handles:
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+ m.select(1.0)
|
|
+
|
|
+ m.remove_handle(c2)
|
|
+ m.remove_handle(c1)
|
|
+ del m.handles
|
|
+ m.close()
|
|
+ c1.close()
|
|
+ c2.close()
|
|
+
|
|
+ self.assertEqual('success', io1.getvalue())
|
|
+ self.assertEqual('success', io2.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 5a9488e0e5f75e70faf37b419819ce18878f29ed Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 12:55:42 -0500
|
|
Subject: [PATCH 035/149] Port multi2 test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/app.py | 8 +++++++
|
|
tests/multi_test.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 62 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/app.py b/tests/app.py
|
|
index b173fd6..3b9303b 100644
|
|
--- a/tests/app.py
|
|
+++ b/tests/app.py
|
|
@@ -5,3 +5,11 @@ app = bottle.Bottle()
|
|
@app.route('/success')
|
|
def ok():
|
|
return 'success'
|
|
+
|
|
+@app.route('/status/403')
|
|
+def forbidden():
|
|
+ bottle.abort(403, 'forbidden')
|
|
+
|
|
+@app.route('/status/404')
|
|
+def not_found():
|
|
+ bottle.abort(404, 'not found')
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index 4c0bdaf..fd96e51 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -11,12 +11,15 @@ from . import util
|
|
|
|
setup_module_1, teardown_module_1 = runwsgi.app_runner_setup((app.app, 8380))
|
|
setup_module_2, teardown_module_2 = runwsgi.app_runner_setup((app.app, 8381))
|
|
+setup_module_3, teardown_module_3 = runwsgi.app_runner_setup((app.app, 8382))
|
|
|
|
def setup_module(mod):
|
|
setup_module_1(mod)
|
|
setup_module_2(mod)
|
|
+ setup_module_3(mod)
|
|
|
|
def teardown_module(mod):
|
|
+ teardown_module_3(mod)
|
|
teardown_module_2(mod)
|
|
teardown_module_1(mod)
|
|
|
|
@@ -54,3 +57,54 @@ class MultiTest(unittest.TestCase):
|
|
|
|
self.assertEqual('success', io1.getvalue())
|
|
self.assertEqual('success', io2.getvalue())
|
|
+
|
|
+ def test_multi_status_codes(self):
|
|
+ # init
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.handles = []
|
|
+ urls = [
|
|
+ 'http://localhost:8380/success',
|
|
+ 'http://localhost:8381/status/403',
|
|
+ 'http://localhost:8382/status/404',
|
|
+ ]
|
|
+ for url in urls:
|
|
+ c = pycurl.Curl()
|
|
+ # save info in standard Python attributes
|
|
+ c.url = url.rstrip()
|
|
+ c.body = util.StringIO()
|
|
+ c.http_code = -1
|
|
+ m.handles.append(c)
|
|
+ # pycurl API calls
|
|
+ c.setopt(c.URL, c.url)
|
|
+ c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
+ m.add_handle(c)
|
|
+
|
|
+ # get data
|
|
+ num_handles = len(m.handles)
|
|
+ while num_handles:
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+ # currently no more I/O is pending, could do something in the meantime
|
|
+ # (display a progress bar, etc.)
|
|
+ m.select(0.1)
|
|
+
|
|
+ # close handles
|
|
+ for c in m.handles:
|
|
+ # save info in standard Python attributes
|
|
+ c.http_code = c.getinfo(c.HTTP_CODE)
|
|
+ # pycurl API calls
|
|
+ m.remove_handle(c)
|
|
+ c.close()
|
|
+ m.close()
|
|
+
|
|
+ # check result
|
|
+ self.assertEqual('success', m.handles[0].body.getvalue())
|
|
+ self.assertEqual(200, m.handles[0].http_code)
|
|
+ # bottle generated response body
|
|
+ assert 'Error 403: Forbidden' in m.handles[1].body.getvalue()
|
|
+ self.assertEqual(403, m.handles[1].http_code)
|
|
+ # bottle generated response body
|
|
+ assert 'Error 404: Not Found' in m.handles[2].body.getvalue()
|
|
+ self.assertEqual(404, m.handles[2].http_code)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From ddeba20f213aea07a2491df171b899b2453de70b Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 14:05:49 -0500
|
|
Subject: [PATCH 036/149] Porting multi3 test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 71 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index fd96e51..1c13f70 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -108,3 +108,74 @@ class MultiTest(unittest.TestCase):
|
|
# bottle generated response body
|
|
assert 'Error 404: Not Found' in m.handles[2].body.getvalue()
|
|
self.assertEqual(404, m.handles[2].http_code)
|
|
+
|
|
+ def test_adding_closed_handle(self):
|
|
+ # init
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.handles = []
|
|
+ urls = [
|
|
+ 'http://localhost:8380/success',
|
|
+ 'http://localhost:8381/status/403',
|
|
+ 'http://localhost:8382/status/404',
|
|
+ ]
|
|
+ for url in urls:
|
|
+ c = pycurl.Curl()
|
|
+ # save info in standard Python attributes
|
|
+ c.url = url
|
|
+ c.body = util.StringIO()
|
|
+ c.http_code = -1
|
|
+ c.debug = 0
|
|
+ m.handles.append(c)
|
|
+ # pycurl API calls
|
|
+ c.setopt(c.URL, c.url)
|
|
+ c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
+ m.add_handle(c)
|
|
+
|
|
+ # debug - close a handle
|
|
+ c = m.handles[2]
|
|
+ c.debug = 1
|
|
+ c.close()
|
|
+
|
|
+ # get data
|
|
+ num_handles = len(m.handles)
|
|
+ while num_handles:
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+ # currently no more I/O is pending, could do something in the meantime
|
|
+ # (display a progress bar, etc.)
|
|
+ m.select(0.1)
|
|
+
|
|
+ # close handles
|
|
+ for c in m.handles:
|
|
+ # save info in standard Python attributes
|
|
+ try:
|
|
+ c.http_code = c.getinfo(c.HTTP_CODE)
|
|
+ except pycurl.error:
|
|
+ # handle already closed - see debug above
|
|
+ assert c.debug
|
|
+ c.http_code = -1
|
|
+ # pycurl API calls
|
|
+ if 0:
|
|
+ m.remove_handle(c)
|
|
+ c.close()
|
|
+ elif 0:
|
|
+ # in the C API this is the wrong calling order, but pycurl
|
|
+ # handles this automatically
|
|
+ c.close()
|
|
+ m.remove_handle(c)
|
|
+ else:
|
|
+ # actually, remove_handle is called automatically on close
|
|
+ c.close()
|
|
+ m.close()
|
|
+
|
|
+ # check result
|
|
+ self.assertEqual('success', m.handles[0].body.getvalue())
|
|
+ self.assertEqual(200, m.handles[0].http_code)
|
|
+ # bottle generated response body
|
|
+ assert 'Error 403: Forbidden' in m.handles[1].body.getvalue()
|
|
+ self.assertEqual(403, m.handles[1].http_code)
|
|
+ # bottle generated response body
|
|
+ self.assertEqual('', m.handles[2].body.getvalue())
|
|
+ self.assertEqual(-1, m.handles[2].http_code)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bd01383371db110534ea39c4ce35563d63a21f73 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 14:15:13 -0500
|
|
Subject: [PATCH 037/149] Exercise all 3 possibilites in ported multi3 test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 37 +++++++++++++++++++++++++------------
|
|
1 files changed, 25 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index 1c13f70..e1fec05 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -109,7 +109,7 @@ class MultiTest(unittest.TestCase):
|
|
assert 'Error 404: Not Found' in m.handles[2].body.getvalue()
|
|
self.assertEqual(404, m.handles[2].http_code)
|
|
|
|
- def test_adding_closed_handle(self):
|
|
+ def check_adding_closed_handle(self, close_fn):
|
|
# init
|
|
m = pycurl.CurlMulti()
|
|
m.handles = []
|
|
@@ -157,17 +157,7 @@ class MultiTest(unittest.TestCase):
|
|
assert c.debug
|
|
c.http_code = -1
|
|
# pycurl API calls
|
|
- if 0:
|
|
- m.remove_handle(c)
|
|
- c.close()
|
|
- elif 0:
|
|
- # in the C API this is the wrong calling order, but pycurl
|
|
- # handles this automatically
|
|
- c.close()
|
|
- m.remove_handle(c)
|
|
- else:
|
|
- # actually, remove_handle is called automatically on close
|
|
- c.close()
|
|
+ close_fn(m, c)
|
|
m.close()
|
|
|
|
# check result
|
|
@@ -179,3 +169,26 @@ class MultiTest(unittest.TestCase):
|
|
# bottle generated response body
|
|
self.assertEqual('', m.handles[2].body.getvalue())
|
|
self.assertEqual(-1, m.handles[2].http_code)
|
|
+
|
|
+ def _remove_then_close(self, m, c):
|
|
+ m.remove_handle(c)
|
|
+ c.close()
|
|
+
|
|
+ def _close_then_remove(self, m, c):
|
|
+ # in the C API this is the wrong calling order, but pycurl
|
|
+ # handles this automatically
|
|
+ c.close()
|
|
+ m.remove_handle(c)
|
|
+
|
|
+ def _close_without_removing(self, m, c):
|
|
+ # actually, remove_handle is called automatically on close
|
|
+ c.close
|
|
+
|
|
+ def test_adding_closed_handle_remove_then_close(self):
|
|
+ self.check_adding_closed_handle(self._remove_then_close)
|
|
+
|
|
+ def test_adding_closed_handle_close_then_remove(self):
|
|
+ self.check_adding_closed_handle(self._close_then_remove)
|
|
+
|
|
+ def test_adding_closed_handle_close_without_removing(self):
|
|
+ self.check_adding_closed_handle(self._close_without_removing)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 587c4b3403bf16ce5ab8a72e738ac26dab4a31c8 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 3 Mar 2013 14:21:33 -0500
|
|
Subject: [PATCH 038/149] Port mulit4 test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 50 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index e1fec05..a508809 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -4,6 +4,7 @@
|
|
|
|
import pycurl
|
|
import unittest
|
|
+import select
|
|
|
|
from . import app
|
|
from . import runwsgi
|
|
@@ -58,6 +59,55 @@ class MultiTest(unittest.TestCase):
|
|
self.assertEqual('success', io1.getvalue())
|
|
self.assertEqual('success', io2.getvalue())
|
|
|
|
+ def test_multi_select_fdset(self):
|
|
+ c1 = pycurl.Curl()
|
|
+ c2 = pycurl.Curl()
|
|
+ c3 = pycurl.Curl()
|
|
+ c1.setopt(c1.URL, "http://localhost:8380/success")
|
|
+ c2.setopt(c2.URL, "http://localhost:8381/success")
|
|
+ c3.setopt(c3.URL, "http://localhost:8382/success")
|
|
+ c1.body = util.StringIO()
|
|
+ c2.body = util.StringIO()
|
|
+ c3.body = util.StringIO()
|
|
+ c1.setopt(c1.WRITEFUNCTION, c1.body.write)
|
|
+ c2.setopt(c2.WRITEFUNCTION, c2.body.write)
|
|
+ c3.setopt(c3.WRITEFUNCTION, c3.body.write)
|
|
+
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.add_handle(c1)
|
|
+ m.add_handle(c2)
|
|
+ m.add_handle(c3)
|
|
+
|
|
+ # Number of seconds to wait for a timeout to happen
|
|
+ SELECT_TIMEOUT = 0.1
|
|
+
|
|
+ # Stir the state machine into action
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+
|
|
+ # Keep going until all the connections have terminated
|
|
+ while num_handles:
|
|
+ select.select(*m.fdset() + (SELECT_TIMEOUT,))
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+
|
|
+ # Cleanup
|
|
+ m.remove_handle(c3)
|
|
+ m.remove_handle(c2)
|
|
+ m.remove_handle(c1)
|
|
+ m.close()
|
|
+ c1.close()
|
|
+ c2.close()
|
|
+ c3.close()
|
|
+
|
|
+ self.assertEqual('success', c1.body.getvalue())
|
|
+ self.assertEqual('success', c2.body.getvalue())
|
|
+ self.assertEqual('success', c3.body.getvalue())
|
|
+
|
|
def test_multi_status_codes(self):
|
|
# init
|
|
m = pycurl.CurlMulti()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From cd0e96615c24173e38177395931899aaa566c270 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 00:24:44 -0500
|
|
Subject: [PATCH 039/149] Port multit6 test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 55 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index a508809..e83ce48 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -242,3 +242,58 @@ class MultiTest(unittest.TestCase):
|
|
|
|
def test_adding_closed_handle_close_without_removing(self):
|
|
self.check_adding_closed_handle(self._close_without_removing)
|
|
+
|
|
+ def test_multi_info_read(self):
|
|
+ c1 = pycurl.Curl()
|
|
+ c2 = pycurl.Curl()
|
|
+ c3 = pycurl.Curl()
|
|
+ c1.setopt(c1.URL, "http://localhost:8380/success")
|
|
+ c2.setopt(c2.URL, "http://localhost:8381/success")
|
|
+ c3.setopt(c3.URL, "http://localhost:8382/success")
|
|
+ c1.body = util.StringIO()
|
|
+ c2.body = util.StringIO()
|
|
+ c3.body = util.StringIO()
|
|
+ c1.setopt(c1.WRITEFUNCTION, c1.body.write)
|
|
+ c2.setopt(c2.WRITEFUNCTION, c2.body.write)
|
|
+ c3.setopt(c3.WRITEFUNCTION, c3.body.write)
|
|
+
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.add_handle(c1)
|
|
+ m.add_handle(c2)
|
|
+ m.add_handle(c3)
|
|
+
|
|
+ # Number of seconds to wait for a timeout to happen
|
|
+ SELECT_TIMEOUT = 1.0
|
|
+
|
|
+ # Stir the state machine into action
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+
|
|
+ # Keep going until all the connections have terminated
|
|
+ while num_handles:
|
|
+ # The select method uses fdset internally to determine which file descriptors
|
|
+ # to check.
|
|
+ m.select(SELECT_TIMEOUT)
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ # Print the message, if any
|
|
+ while True:
|
|
+ info = m.info_read()
|
|
+ print info
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+
|
|
+ # Cleanup
|
|
+ m.remove_handle(c3)
|
|
+ m.remove_handle(c2)
|
|
+ m.remove_handle(c1)
|
|
+ m.close()
|
|
+ c1.close()
|
|
+ c2.close()
|
|
+ c3.close()
|
|
+
|
|
+ self.assertEqual('success', c1.body.getvalue())
|
|
+ self.assertEqual('success', c2.body.getvalue())
|
|
+ self.assertEqual('success', c3.body.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d59cc0dffc1f70545317c03307211559afe46b6d Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 00:38:59 -0500
|
|
Subject: [PATCH 040/149] Improve info_read test to test info_read
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 19 +++++++++++++++----
|
|
1 files changed, 15 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index e83ce48..10af44c 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -271,6 +271,7 @@ class MultiTest(unittest.TestCase):
|
|
if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
break
|
|
|
|
+ infos = []
|
|
# Keep going until all the connections have terminated
|
|
while num_handles:
|
|
# The select method uses fdset internally to determine which file descriptors
|
|
@@ -278,13 +279,23 @@ class MultiTest(unittest.TestCase):
|
|
m.select(SELECT_TIMEOUT)
|
|
while 1:
|
|
ret, num_handles = m.perform()
|
|
- # Print the message, if any
|
|
- while True:
|
|
- info = m.info_read()
|
|
- print info
|
|
+ info = m.info_read()
|
|
+ infos.append(info)
|
|
if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
break
|
|
|
|
+ all_handles = []
|
|
+ for info in infos:
|
|
+ handles = info[1]
|
|
+ # last info is an empty array
|
|
+ if handles:
|
|
+ all_handles.extend(handles)
|
|
+
|
|
+ self.assertEqual(3, len(all_handles))
|
|
+ assert c1 in all_handles
|
|
+ assert c2 in all_handles
|
|
+ assert c3 in all_handles
|
|
+
|
|
# Cleanup
|
|
m.remove_handle(c3)
|
|
m.remove_handle(c2)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 9b239643fd425e600b467f91ce7ea0560dd88b79 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 00:40:25 -0500
|
|
Subject: [PATCH 041/149] Port multi5 test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 51 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index 10af44c..d9c6174 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -243,6 +243,57 @@ class MultiTest(unittest.TestCase):
|
|
def test_adding_closed_handle_close_without_removing(self):
|
|
self.check_adding_closed_handle(self._close_without_removing)
|
|
|
|
+ def test_multi_select(self):
|
|
+ c1 = pycurl.Curl()
|
|
+ c2 = pycurl.Curl()
|
|
+ c3 = pycurl.Curl()
|
|
+ c1.setopt(c1.URL, "http://localhost:8380/success")
|
|
+ c2.setopt(c2.URL, "http://localhost:8381/success")
|
|
+ c3.setopt(c3.URL, "http://localhost:8382/success")
|
|
+ c1.body = util.StringIO()
|
|
+ c2.body = util.StringIO()
|
|
+ c3.body = util.StringIO()
|
|
+ c1.setopt(c1.WRITEFUNCTION, c1.body.write)
|
|
+ c2.setopt(c2.WRITEFUNCTION, c2.body.write)
|
|
+ c3.setopt(c3.WRITEFUNCTION, c3.body.write)
|
|
+
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.add_handle(c1)
|
|
+ m.add_handle(c2)
|
|
+ m.add_handle(c3)
|
|
+
|
|
+ # Number of seconds to wait for a timeout to happen
|
|
+ SELECT_TIMEOUT = 1.0
|
|
+
|
|
+ # Stir the state machine into action
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+
|
|
+ # Keep going until all the connections have terminated
|
|
+ while num_handles:
|
|
+ # The select method uses fdset internally to determine which file descriptors
|
|
+ # to check.
|
|
+ m.select(SELECT_TIMEOUT)
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+
|
|
+ # Cleanup
|
|
+ m.remove_handle(c3)
|
|
+ m.remove_handle(c2)
|
|
+ m.remove_handle(c1)
|
|
+ m.close()
|
|
+ c1.close()
|
|
+ c2.close()
|
|
+ c3.close()
|
|
+
|
|
+ self.assertEqual('success', c1.body.getvalue())
|
|
+ self.assertEqual('success', c2.body.getvalue())
|
|
+ self.assertEqual('success', c3.body.getvalue())
|
|
+
|
|
def test_multi_info_read(self):
|
|
c1 = pycurl.Curl()
|
|
c2 = pycurl.Curl()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c16f8df53e9f97d2ef4c0acb19e4abcda5825260 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 22:05:34 -0500
|
|
Subject: [PATCH 042/149] Ported test_multi_socket.py
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_socket_test.py | 110 ++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 110 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/multi_socket_test.py
|
|
|
|
diff --git a/tests/multi_socket_test.py b/tests/multi_socket_test.py
|
|
new file mode 100644
|
|
index 0000000..2586569
|
|
--- /dev/null
|
|
+++ b/tests/multi_socket_test.py
|
|
@@ -0,0 +1,110 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import select
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module_1, teardown_module_1 = runwsgi.app_runner_setup((app.app, 8380))
|
|
+setup_module_2, teardown_module_2 = runwsgi.app_runner_setup((app.app, 8381))
|
|
+setup_module_3, teardown_module_3 = runwsgi.app_runner_setup((app.app, 8382))
|
|
+
|
|
+def setup_module(mod):
|
|
+ setup_module_1(mod)
|
|
+ setup_module_2(mod)
|
|
+ setup_module_3(mod)
|
|
+
|
|
+def teardown_module(mod):
|
|
+ teardown_module_3(mod)
|
|
+ teardown_module_2(mod)
|
|
+ teardown_module_1(mod)
|
|
+
|
|
+class MultiSocketTest(unittest.TestCase):
|
|
+ def test_multi_socket(self):
|
|
+ urls = [
|
|
+ 'http://localhost:8380/success',
|
|
+ 'http://localhost:8381/success',
|
|
+ 'http://localhost:8382/success',
|
|
+ ]
|
|
+
|
|
+ timers = []
|
|
+
|
|
+ # timer callback
|
|
+ def timer(msecs):
|
|
+ #print('Timer callback msecs:', msecs)
|
|
+ timers.append(msecs)
|
|
+
|
|
+ socket_events = []
|
|
+
|
|
+ # socket callback
|
|
+ def socket(event, socket, multi, data):
|
|
+ #print(event, socket, multi, data)
|
|
+ # multi.assign(socket, timer)
|
|
+ socket_events.append((event, multi))
|
|
+
|
|
+ # init
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.setopt(pycurl.M_PIPELINING, 1)
|
|
+ m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
+ m.setopt(pycurl.M_SOCKETFUNCTION, socket)
|
|
+ m.handles = []
|
|
+ for url in urls:
|
|
+ c = pycurl.Curl()
|
|
+ # save info in standard Python attributes
|
|
+ c.url = url
|
|
+ c.body = util.StringIO()
|
|
+ c.http_code = -1
|
|
+ m.handles.append(c)
|
|
+ # pycurl API calls
|
|
+ c.setopt(c.URL, c.url)
|
|
+ c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
+ m.add_handle(c)
|
|
+
|
|
+ # get data
|
|
+ num_handles = len(m.handles)
|
|
+ while num_handles:
|
|
+ while 1:
|
|
+ ret, num_handles = m.socket_all()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+ # currently no more I/O is pending, could do something in the meantime
|
|
+ # (display a progress bar, etc.)
|
|
+ m.select(0.1)
|
|
+
|
|
+ for c in m.handles:
|
|
+ # save info in standard Python attributes
|
|
+ c.http_code = c.getinfo(c.HTTP_CODE)
|
|
+
|
|
+ # at least in and remove events per socket
|
|
+ assert len(socket_events) >= 6
|
|
+
|
|
+ # print result
|
|
+ for c in m.handles:
|
|
+ self.assertEqual('success', c.body.getvalue())
|
|
+ self.assertEqual(200, c.http_code)
|
|
+
|
|
+ # multi, not curl handle
|
|
+ self.check(pycurl.POLL_IN, m, socket_events)
|
|
+ self.check(pycurl.POLL_REMOVE, m, socket_events)
|
|
+
|
|
+ assert len(timers) > 0
|
|
+ assert timers[0] > 0
|
|
+ self.assertEqual(-1, timers[-1])
|
|
+
|
|
+ # close handles
|
|
+ for c in m.handles:
|
|
+ # pycurl API calls
|
|
+ m.remove_handle(c)
|
|
+ c.close()
|
|
+ m.close()
|
|
+
|
|
+ def check(self, event, multi, socket_events):
|
|
+ for event_, multi_ in socket_events:
|
|
+ if event == event_ and multi == multi_:
|
|
+ return
|
|
+ assert False, '%d %s not found in socket events' % (event, multi)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 9a0ae278c27b16fa7dc745c2add39101a13fc9ec Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 22:29:45 -0500
|
|
Subject: [PATCH 043/149] Ported test_multi_socket_select.py
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_socket_select_test.py | 130 +++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 130 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/multi_socket_select_test.py
|
|
|
|
diff --git a/tests/multi_socket_select_test.py b/tests/multi_socket_select_test.py
|
|
new file mode 100644
|
|
index 0000000..b9ba950
|
|
--- /dev/null
|
|
+++ b/tests/multi_socket_select_test.py
|
|
@@ -0,0 +1,130 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import select
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module_1, teardown_module_1 = runwsgi.app_runner_setup((app.app, 8380))
|
|
+setup_module_2, teardown_module_2 = runwsgi.app_runner_setup((app.app, 8381))
|
|
+setup_module_3, teardown_module_3 = runwsgi.app_runner_setup((app.app, 8382))
|
|
+
|
|
+def setup_module(mod):
|
|
+ setup_module_1(mod)
|
|
+ setup_module_2(mod)
|
|
+ setup_module_3(mod)
|
|
+
|
|
+def teardown_module(mod):
|
|
+ teardown_module_3(mod)
|
|
+ teardown_module_2(mod)
|
|
+ teardown_module_1(mod)
|
|
+
|
|
+class MultiSocketSelectTest(unittest.TestCase):
|
|
+ def test_multi_socket_select(self):
|
|
+ sockets = set()
|
|
+ timeout = 0
|
|
+
|
|
+ urls = [
|
|
+ 'http://localhost:8380/success',
|
|
+ 'http://localhost:8381/success',
|
|
+ 'http://localhost:8382/success',
|
|
+ ]
|
|
+
|
|
+ timers = []
|
|
+
|
|
+ # timer callback
|
|
+ def timer(msecs):
|
|
+ #print('Timer callback msecs:', msecs)
|
|
+ timers.append(msecs)
|
|
+
|
|
+ socket_events = []
|
|
+
|
|
+ # socket callback
|
|
+ def socket(event, socket, multi, data):
|
|
+ if event == pycurl.POLL_REMOVE:
|
|
+ #print("Remove Socket %d"%socket)
|
|
+ sockets.remove(socket)
|
|
+ else:
|
|
+ if socket not in sockets:
|
|
+ #print("Add socket %d"%socket)
|
|
+ sockets.add(socket)
|
|
+ socket_events.append((event, multi))
|
|
+
|
|
+ # init
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.setopt(pycurl.M_PIPELINING, 1)
|
|
+ m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
+ m.setopt(pycurl.M_SOCKETFUNCTION, socket)
|
|
+ m.handles = []
|
|
+ for url in urls:
|
|
+ c = pycurl.Curl()
|
|
+ # save info in standard Python attributes
|
|
+ c.url = url
|
|
+ c.body = util.StringIO()
|
|
+ c.http_code = -1
|
|
+ m.handles.append(c)
|
|
+ # pycurl API calls
|
|
+ c.setopt(c.URL, c.url)
|
|
+ c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
+ m.add_handle(c)
|
|
+
|
|
+ # get data
|
|
+ num_handles = len(m.handles)
|
|
+
|
|
+ while (pycurl.E_CALL_MULTI_PERFORM==m.socket_all()[0]):
|
|
+ pass
|
|
+
|
|
+ timeout = m.timeout()
|
|
+
|
|
+
|
|
+ while True:
|
|
+ (rr, wr, er) = select.select(sockets,sockets,sockets,timeout/1000.0)
|
|
+ socketSet = set(rr+wr+er)
|
|
+ if socketSet:
|
|
+ for s in socketSet:
|
|
+ while True:
|
|
+ (ret,running) = m.socket_action(s,0)
|
|
+ if ret!=pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+ else:
|
|
+ (ret,running) = m.socket_action(pycurl.SOCKET_TIMEOUT,0)
|
|
+ if running==0:
|
|
+ break
|
|
+
|
|
+ for c in m.handles:
|
|
+ # save info in standard Python attributes
|
|
+ c.http_code = c.getinfo(c.HTTP_CODE)
|
|
+
|
|
+ # at least in and remove events per socket
|
|
+ assert len(socket_events) >= 6
|
|
+
|
|
+ # print result
|
|
+ for c in m.handles:
|
|
+ self.assertEqual('success', c.body.getvalue())
|
|
+ self.assertEqual(200, c.http_code)
|
|
+
|
|
+ # multi, not curl handle
|
|
+ self.check(pycurl.POLL_IN, m, socket_events)
|
|
+ self.check(pycurl.POLL_REMOVE, m, socket_events)
|
|
+
|
|
+ assert len(timers) > 0
|
|
+ assert timers[0] > 0
|
|
+ self.assertEqual(-1, timers[-1])
|
|
+
|
|
+ # close handles
|
|
+ for c in m.handles:
|
|
+ # pycurl API calls
|
|
+ m.remove_handle(c)
|
|
+ c.close()
|
|
+ m.close()
|
|
+
|
|
+ def check(self, event, multi, socket_events):
|
|
+ for event_, multi_ in socket_events:
|
|
+ if event == event_ and multi == multi_:
|
|
+ return
|
|
+ assert False, '%d %s not found in socket events' % (event, multi)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 7631c7c047354c1dacb09459fefd6ea9ca11a28b Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:15:47 -0500
|
|
Subject: [PATCH 044/149] Ported test_multi_timer.py
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_timer_test.py | 88 +++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 88 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/multi_timer_test.py
|
|
|
|
diff --git a/tests/multi_timer_test.py b/tests/multi_timer_test.py
|
|
new file mode 100644
|
|
index 0000000..e961780
|
|
--- /dev/null
|
|
+++ b/tests/multi_timer_test.py
|
|
@@ -0,0 +1,88 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import select
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module_1, teardown_module_1 = runwsgi.app_runner_setup((app.app, 8380))
|
|
+setup_module_2, teardown_module_2 = runwsgi.app_runner_setup((app.app, 8381))
|
|
+setup_module_3, teardown_module_3 = runwsgi.app_runner_setup((app.app, 8382))
|
|
+
|
|
+def setup_module(mod):
|
|
+ setup_module_1(mod)
|
|
+ setup_module_2(mod)
|
|
+ setup_module_3(mod)
|
|
+
|
|
+def teardown_module(mod):
|
|
+ teardown_module_3(mod)
|
|
+ teardown_module_2(mod)
|
|
+ teardown_module_1(mod)
|
|
+
|
|
+class MultiSocketTest(unittest.TestCase):
|
|
+ def test_multi_timer(self):
|
|
+ urls = [
|
|
+ 'http://localhost:8380/success',
|
|
+ 'http://localhost:8381/success',
|
|
+ 'http://localhost:8382/success',
|
|
+ ]
|
|
+
|
|
+ timers = []
|
|
+
|
|
+ # timer callback
|
|
+ def timer(msecs):
|
|
+ #print('Timer callback msecs:', msecs)
|
|
+ timers.append(msecs)
|
|
+
|
|
+ # init
|
|
+ m = pycurl.CurlMulti()
|
|
+ m.setopt(pycurl.M_PIPELINING, 1)
|
|
+ m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
+ m.handles = []
|
|
+ for url in urls:
|
|
+ c = pycurl.Curl()
|
|
+ # save info in standard Python attributes
|
|
+ c.url = url
|
|
+ c.body = util.StringIO()
|
|
+ c.http_code = -1
|
|
+ m.handles.append(c)
|
|
+ # pycurl API calls
|
|
+ c.setopt(c.URL, c.url)
|
|
+ c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
+ m.add_handle(c)
|
|
+
|
|
+ # get data
|
|
+ num_handles = len(m.handles)
|
|
+ while num_handles:
|
|
+ while 1:
|
|
+ ret, num_handles = m.perform()
|
|
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
+ break
|
|
+ # currently no more I/O is pending, could do something in the meantime
|
|
+ # (display a progress bar, etc.)
|
|
+ m.select(1.0)
|
|
+
|
|
+ for c in m.handles:
|
|
+ # save info in standard Python attributes
|
|
+ c.http_code = c.getinfo(c.HTTP_CODE)
|
|
+
|
|
+ # print result
|
|
+ for c in m.handles:
|
|
+ self.assertEqual('success', c.body.getvalue())
|
|
+ self.assertEqual(200, c.http_code)
|
|
+
|
|
+ assert len(timers) > 0
|
|
+ assert timers[0] > 0
|
|
+ self.assertEqual(-1, timers[-1])
|
|
+
|
|
+ # close handles
|
|
+ for c in m.handles:
|
|
+ # pycurl API calls
|
|
+ m.remove_handle(c)
|
|
+ c.close()
|
|
+ m.close()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From eb523b0b4e3729d6613e1841d3d3715ad6e58109 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:17:14 -0500
|
|
Subject: [PATCH 045/149] Timers are tested in multi_timer test, delete them from other multi tests
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_socket_select_test.py | 12 ------------
|
|
tests/multi_socket_test.py | 13 -------------
|
|
2 files changed, 0 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/tests/multi_socket_select_test.py b/tests/multi_socket_select_test.py
|
|
index b9ba950..0c472cf 100644
|
|
--- a/tests/multi_socket_select_test.py
|
|
+++ b/tests/multi_socket_select_test.py
|
|
@@ -35,13 +35,6 @@ class MultiSocketSelectTest(unittest.TestCase):
|
|
'http://localhost:8382/success',
|
|
]
|
|
|
|
- timers = []
|
|
-
|
|
- # timer callback
|
|
- def timer(msecs):
|
|
- #print('Timer callback msecs:', msecs)
|
|
- timers.append(msecs)
|
|
-
|
|
socket_events = []
|
|
|
|
# socket callback
|
|
@@ -58,7 +51,6 @@ class MultiSocketSelectTest(unittest.TestCase):
|
|
# init
|
|
m = pycurl.CurlMulti()
|
|
m.setopt(pycurl.M_PIPELINING, 1)
|
|
- m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
m.setopt(pycurl.M_SOCKETFUNCTION, socket)
|
|
m.handles = []
|
|
for url in urls:
|
|
@@ -112,10 +104,6 @@ class MultiSocketSelectTest(unittest.TestCase):
|
|
self.check(pycurl.POLL_IN, m, socket_events)
|
|
self.check(pycurl.POLL_REMOVE, m, socket_events)
|
|
|
|
- assert len(timers) > 0
|
|
- assert timers[0] > 0
|
|
- self.assertEqual(-1, timers[-1])
|
|
-
|
|
# close handles
|
|
for c in m.handles:
|
|
# pycurl API calls
|
|
diff --git a/tests/multi_socket_test.py b/tests/multi_socket_test.py
|
|
index 2586569..2cce7ae 100644
|
|
--- a/tests/multi_socket_test.py
|
|
+++ b/tests/multi_socket_test.py
|
|
@@ -32,25 +32,16 @@ class MultiSocketTest(unittest.TestCase):
|
|
'http://localhost:8382/success',
|
|
]
|
|
|
|
- timers = []
|
|
-
|
|
- # timer callback
|
|
- def timer(msecs):
|
|
- #print('Timer callback msecs:', msecs)
|
|
- timers.append(msecs)
|
|
-
|
|
socket_events = []
|
|
|
|
# socket callback
|
|
def socket(event, socket, multi, data):
|
|
#print(event, socket, multi, data)
|
|
- # multi.assign(socket, timer)
|
|
socket_events.append((event, multi))
|
|
|
|
# init
|
|
m = pycurl.CurlMulti()
|
|
m.setopt(pycurl.M_PIPELINING, 1)
|
|
- m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
m.setopt(pycurl.M_SOCKETFUNCTION, socket)
|
|
m.handles = []
|
|
for url in urls:
|
|
@@ -92,10 +83,6 @@ class MultiSocketTest(unittest.TestCase):
|
|
self.check(pycurl.POLL_IN, m, socket_events)
|
|
self.check(pycurl.POLL_REMOVE, m, socket_events)
|
|
|
|
- assert len(timers) > 0
|
|
- assert timers[0] > 0
|
|
- self.assertEqual(-1, timers[-1])
|
|
-
|
|
# close handles
|
|
for c in m.handles:
|
|
# pycurl API calls
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c4ad7c4b2cf2107fb4dfcf468fef554bb8f1a38f Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:30:48 -0500
|
|
Subject: [PATCH 046/149] Ported post test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/app.py | 5 +++++
|
|
tests/post_test.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 54 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/post_test.py
|
|
|
|
diff --git a/tests/app.py b/tests/app.py
|
|
index 3b9303b..1fa09a6 100644
|
|
--- a/tests/app.py
|
|
+++ b/tests/app.py
|
|
@@ -1,4 +1,5 @@
|
|
import bottle
|
|
+import json
|
|
|
|
app = bottle.Bottle()
|
|
|
|
@@ -13,3 +14,7 @@ def forbidden():
|
|
@app.route('/status/404')
|
|
def not_found():
|
|
bottle.abort(404, 'not found')
|
|
+
|
|
+@app.route('/postfields', method='post')
|
|
+def postfields():
|
|
+ return json.dumps(dict(bottle.request.forms))
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
new file mode 100644
|
|
index 0000000..183c4c9
|
|
--- /dev/null
|
|
+++ b/tests/post_test.py
|
|
@@ -0,0 +1,49 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import io
|
|
+import json
|
|
+try:
|
|
+ import urllib.parse as urllib_parse
|
|
+except ImportError:
|
|
+ import urllib as urllib_parse
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class PostTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_post_single_field(self):
|
|
+ pf = {'field1': 'value1'}
|
|
+ self.check(pf)
|
|
+
|
|
+ def test_post_multiple_fields(self):
|
|
+ pf = {'field1':'value1', 'field2':'value2 with blanks', 'field3':'value3'}
|
|
+ self.check(pf)
|
|
+
|
|
+ def test_post_fields_with_ampersand(self):
|
|
+ pf = {'field1':'value1', 'field2':'value2 with blanks and & chars',
|
|
+ 'field3':'value3'}
|
|
+ self.check(pf)
|
|
+
|
|
+ def check(self, pf):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/postfields')
|
|
+ self.curl.setopt(pycurl.POSTFIELDS, urllib_parse.urlencode(pf))
|
|
+ #self.curl.setopt(pycurl.VERBOSE, 1)
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+ body = sio.getvalue()
|
|
+ returned_fields = json.loads(body)
|
|
+ self.assertEqual(pf, returned_fields)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 789b647eff13181fa527cb218dd487695abf3515 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:35:02 -0500
|
|
Subject: [PATCH 047/149] Port test_post2.py null byte test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/post_test.py | 28 ++++++++++++++++++++++++----
|
|
1 files changed, 24 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index 183c4c9..6f9cf80 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -26,18 +26,18 @@ class PostTest(unittest.TestCase):
|
|
|
|
def test_post_single_field(self):
|
|
pf = {'field1': 'value1'}
|
|
- self.check(pf)
|
|
+ self.urlencode_and_check(pf)
|
|
|
|
def test_post_multiple_fields(self):
|
|
pf = {'field1':'value1', 'field2':'value2 with blanks', 'field3':'value3'}
|
|
- self.check(pf)
|
|
+ self.urlencode_and_check(pf)
|
|
|
|
def test_post_fields_with_ampersand(self):
|
|
pf = {'field1':'value1', 'field2':'value2 with blanks and & chars',
|
|
'field3':'value3'}
|
|
- self.check(pf)
|
|
+ self.urlencode_and_check(pf)
|
|
|
|
- def check(self, pf):
|
|
+ def urlencode_and_check(self, pf):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/postfields')
|
|
self.curl.setopt(pycurl.POSTFIELDS, urllib_parse.urlencode(pf))
|
|
#self.curl.setopt(pycurl.VERBOSE, 1)
|
|
@@ -47,3 +47,23 @@ class PostTest(unittest.TestCase):
|
|
body = sio.getvalue()
|
|
returned_fields = json.loads(body)
|
|
self.assertEqual(pf, returned_fields)
|
|
+
|
|
+ def test_post_with_null_byte(self):
|
|
+ send = [
|
|
+ ('field3', (pycurl.FORM_CONTENTS, 'this is wei\000rd, but null-bytes are okay'))
|
|
+ ]
|
|
+ expect = {
|
|
+ 'field3': 'this is wei\000rd, but null-bytes are okay',
|
|
+ }
|
|
+ self.check_post(send, expect)
|
|
+
|
|
+ def check_post(self, send, expect):
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/postfields')
|
|
+ self.curl.setopt(pycurl.HTTPPOST, send)
|
|
+ #self.curl.setopt(pycurl.VERBOSE, 1)
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+ body = sio.getvalue()
|
|
+ returned_fields = json.loads(body)
|
|
+ self.assertEqual(expect, returned_fields)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2f56e4844e78280410f781b04d43ac49ce08129e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:50:51 -0500
|
|
Subject: [PATCH 048/149] Port test_post2.py file upload test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/app.py | 24 ++++++++++++++++++++++++
|
|
tests/post_test.py | 22 +++++++++++++++++++---
|
|
2 files changed, 43 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/tests/app.py b/tests/app.py
|
|
index 1fa09a6..a83e628 100644
|
|
--- a/tests/app.py
|
|
+++ b/tests/app.py
|
|
@@ -18,3 +18,27 @@ def not_found():
|
|
@app.route('/postfields', method='post')
|
|
def postfields():
|
|
return json.dumps(dict(bottle.request.forms))
|
|
+
|
|
+# XXX file is not a bottle FileUpload instance, but FieldStorage?
|
|
+def convert_file(key, file):
|
|
+ return {
|
|
+ 'key': key,
|
|
+ 'name': file.name,
|
|
+ 'raw_filename': file.raw_filename,
|
|
+ 'headers': file.headers,
|
|
+ 'content_type': file.content_type,
|
|
+ 'content_length': file.content_length,
|
|
+ 'data': file.read(),
|
|
+ }
|
|
+
|
|
+def convert_file(key, file):
|
|
+ return {
|
|
+ 'name': file.name,
|
|
+ 'filename': file.filename,
|
|
+ 'data': file.file.read(),
|
|
+ }
|
|
+
|
|
+@app.route('/files', method='post')
|
|
+def files():
|
|
+ files = [convert_file(key, bottle.request.files[key]) for key in bottle.request.files]
|
|
+ return json.dumps(files)
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index 6f9cf80..7df0f3b 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -2,6 +2,7 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
+import os.path
|
|
import pycurl
|
|
import unittest
|
|
import io
|
|
@@ -55,10 +56,25 @@ class PostTest(unittest.TestCase):
|
|
expect = {
|
|
'field3': 'this is wei\000rd, but null-bytes are okay',
|
|
}
|
|
- self.check_post(send, expect)
|
|
+ self.check_post(send, expect, 'http://localhost:8380/postfields')
|
|
|
|
- def check_post(self, send, expect):
|
|
- self.curl.setopt(pycurl.URL, 'http://localhost:8380/postfields')
|
|
+ def test_post_file(self):
|
|
+ path = os.path.join(os.path.dirname(__file__), '..', 'README')
|
|
+ with open(path) as f:
|
|
+ contents = f.read()
|
|
+ send = [
|
|
+ #('field2', (pycurl.FORM_FILE, 'test_post.py', pycurl.FORM_FILE, 'test_post2.py')),
|
|
+ ('field2', (pycurl.FORM_FILE, path)),
|
|
+ ]
|
|
+ expect = [{
|
|
+ 'name': 'field2',
|
|
+ 'filename': 'README',
|
|
+ 'data': contents,
|
|
+ }]
|
|
+ self.check_post(send, expect, 'http://localhost:8380/files')
|
|
+
|
|
+ def check_post(self, send, expect, endpoint):
|
|
+ self.curl.setopt(pycurl.URL, endpoint)
|
|
self.curl.setopt(pycurl.HTTPPOST, send)
|
|
#self.curl.setopt(pycurl.VERBOSE, 1)
|
|
sio = util.StringIO()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c8f91c64ad1eb067907e9b97bd5f8bfa27c29062 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:51:45 -0500
|
|
Subject: [PATCH 049/149] Add a note that this test takes forever to run
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/post_test.py | 1 +
|
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index 7df0f3b..564d043 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -73,6 +73,7 @@ class PostTest(unittest.TestCase):
|
|
}]
|
|
self.check_post(send, expect, 'http://localhost:8380/files')
|
|
|
|
+ # XXX this test takes about a second to run, check keep-alives?
|
|
def check_post(self, send, expect, endpoint):
|
|
self.curl.setopt(pycurl.URL, endpoint)
|
|
self.curl.setopt(pycurl.HTTPPOST, send)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 9ac9dce97226d34e6bb077a0357063fd23056158 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 5 Mar 2013 23:59:04 -0500
|
|
Subject: [PATCH 050/149] Ported test_post3.py
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/post_with_read_callback_test.py | 60 +++++++++++++++++++++++++++++++++
|
|
1 files changed, 60 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/post_with_read_callback_test.py
|
|
|
|
diff --git a/tests/post_with_read_callback_test.py b/tests/post_with_read_callback_test.py
|
|
new file mode 100644
|
|
index 0000000..a09e83a
|
|
--- /dev/null
|
|
+++ b/tests/post_with_read_callback_test.py
|
|
@@ -0,0 +1,60 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import os.path
|
|
+import pycurl
|
|
+import unittest
|
|
+import io
|
|
+import json
|
|
+try:
|
|
+ import urllib.parse as urllib_parse
|
|
+except ImportError:
|
|
+ import urllib as urllib_parse
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+POSTFIELDS = {
|
|
+ 'field1':'value1',
|
|
+ 'field2':'value2 with blanks',
|
|
+ 'field3':'value3',
|
|
+}
|
|
+POSTSTRING = urllib_parse.urlencode(POSTFIELDS)
|
|
+
|
|
+class DataProvider(object):
|
|
+ def __init__(self):
|
|
+ self.finished = False
|
|
+
|
|
+ def read_cb(self, size):
|
|
+ assert len(POSTSTRING) <= size
|
|
+ if not self.finished:
|
|
+ self.finished = True
|
|
+ return POSTSTRING
|
|
+ else:
|
|
+ # Nothing more to read
|
|
+ return ""
|
|
+
|
|
+class PostWithReadCallbackTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_post_with_read_callback(self):
|
|
+ d = DataProvider()
|
|
+ self.curl.setopt(self.curl.URL, 'http://localhost:8380/postfields')
|
|
+ self.curl.setopt(self.curl.POST, 1)
|
|
+ self.curl.setopt(self.curl.POSTFIELDSIZE, len(POSTSTRING))
|
|
+ self.curl.setopt(self.curl.READFUNCTION, d.read_cb)
|
|
+ #self.curl.setopt(self.curl.VERBOSE, 1)
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+
|
|
+ actual = json.loads(sio.getvalue())
|
|
+ self.assertEqual(POSTFIELDS, actual)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 8a4babacffc0bbeacdfcfb3f9888f26efd6c072c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:10:41 -0500
|
|
Subject: [PATCH 051/149] Ported test_socketopen.py
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/socket_open_test.py | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 45 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/socket_open_test.py
|
|
|
|
diff --git a/tests/socket_open_test.py b/tests/socket_open_test.py
|
|
new file mode 100644
|
|
index 0000000..dff3f65
|
|
--- /dev/null
|
|
+++ b/tests/socket_open_test.py
|
|
@@ -0,0 +1,45 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import socket
|
|
+import pycurl
|
|
+import unittest
|
|
+try:
|
|
+ import urllib.parse as urllib_parse
|
|
+except ImportError:
|
|
+ import urllib as urllib_parse
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+socket_open_called = False
|
|
+
|
|
+def socket_open(family, socktype, protocol):
|
|
+ global socket_open_called
|
|
+ socket_open_called = True
|
|
+
|
|
+ #print(family, socktype, protocol)
|
|
+ s = socket.socket(family, socktype, protocol)
|
|
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
+ return s
|
|
+
|
|
+class SocketOpenTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_socket_open(self):
|
|
+ self.curl.setopt(pycurl.OPENSOCKETFUNCTION, socket_open)
|
|
+ self.curl.setopt(self.curl.URL, 'http://localhost:8380/success')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+
|
|
+ assert socket_open_called
|
|
+ self.assertEqual('success', sio.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bf65a3bac3446950421927da8230216acefebf86 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:13:46 -0500
|
|
Subject: [PATCH 052/149] Ported test_share.py
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/share_test.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 51 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/share_test.py
|
|
|
|
diff --git a/tests/share_test.py b/tests/share_test.py
|
|
new file mode 100644
|
|
index 0000000..7b5da77
|
|
--- /dev/null
|
|
+++ b/tests/share_test.py
|
|
@@ -0,0 +1,51 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import threading
|
|
+import pycurl
|
|
+import unittest
|
|
+try:
|
|
+ import urllib.parse as urllib_parse
|
|
+except ImportError:
|
|
+ import urllib as urllib_parse
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class WorkerThread(threading.Thread):
|
|
+
|
|
+ def __init__(self, share):
|
|
+ threading.Thread.__init__(self)
|
|
+ self.curl = pycurl.Curl()
|
|
+ self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ self.curl.setopt(pycurl.SHARE, share)
|
|
+ self.sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, self.sio.write)
|
|
+
|
|
+ def run(self):
|
|
+ self.curl.perform()
|
|
+ self.curl.close()
|
|
+
|
|
+class ShareTest(unittest.TestCase):
|
|
+ def test_share(self):
|
|
+ s = pycurl.CurlShare()
|
|
+ s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_COOKIE)
|
|
+ s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_DNS)
|
|
+
|
|
+ t1 = WorkerThread(s)
|
|
+ t2 = WorkerThread(s)
|
|
+
|
|
+ t1.start()
|
|
+ t2.start()
|
|
+
|
|
+ t1.join()
|
|
+ t2.join()
|
|
+
|
|
+ del s
|
|
+
|
|
+ self.assertEqual('success', t1.sio.getvalue())
|
|
+ self.assertEqual('success', t2.sio.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c5f46d8247e3cbf3d2a0a2cf74c7daeade97c1d8 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:26:45 -0500
|
|
Subject: [PATCH 053/149] Port test_reset.py, which appears to be broken; skip the ported version for now
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/reset_test.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 76 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/reset_test.py
|
|
|
|
diff --git a/tests/reset_test.py b/tests/reset_test.py
|
|
new file mode 100644
|
|
index 0000000..66b7108
|
|
--- /dev/null
|
|
+++ b/tests/reset_test.py
|
|
@@ -0,0 +1,76 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import sys
|
|
+import pycurl
|
|
+import unittest
|
|
+try:
|
|
+ import urllib.parse as urllib_parse
|
|
+except ImportError:
|
|
+ import urllib as urllib_parse
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class ResetTest(unittest.TestCase):
|
|
+ # XXX this test was broken when it was test_reset.py
|
|
+ def skip_test_reset(self):
|
|
+ outf = util.StringIO()
|
|
+ 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.WRITEFUNCTION, outf.write)
|
|
+ eh.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
+ 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()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 4aba306862de76d584af790bf2dd90f0d55fda0e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:55:41 -0500
|
|
Subject: [PATCH 054/149] Start a server on each port once, different servers should go on different ports
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 9 ++++++++-
|
|
1 files changed, 8 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index 7b39358..6d3b69f 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -48,6 +48,8 @@ class ServerThread(threading.Thread):
|
|
def run(self):
|
|
bottle.run(self.app, server=self.server, quiet=True)
|
|
|
|
+started_servers = {}
|
|
+
|
|
def app_runner_setup(*specs):
|
|
'''Returns setup and teardown methods for running a list of WSGI
|
|
applications in a daemon thread.
|
|
@@ -73,9 +75,14 @@ def app_runner_setup(*specs):
|
|
kwargs = {}
|
|
else:
|
|
app, port, kwargs = spec
|
|
- self.servers.append(start_bottle_server(app, port, **kwargs))
|
|
+ if port in started_servers:
|
|
+ assert started_servers[port] == (app, kwargs)
|
|
+ else:
|
|
+ self.servers.append(start_bottle_server(app, port, **kwargs))
|
|
+ started_servers[port] = (app, kwargs)
|
|
|
|
def teardown(self):
|
|
+ return
|
|
for server in self.servers:
|
|
# if no tests from module were run, there is no server to shut down
|
|
if hasattr(server, 'srv'):
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 8fc24d93e2188d68c738e602c75753cec503de7d Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:56:44 -0500
|
|
Subject: [PATCH 055/149] Need to skip more aggressively it would seem
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 2 +-
|
|
tests/reset_test.py | 2 +-
|
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index a0de66e..c0d256b 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -40,7 +40,7 @@ class DefaultWriteFunctionTest(unittest.TestCase):
|
|
os.fsync(STDOUT_FD_NUM)
|
|
|
|
# I have a really hard time getting this to work with nose output capture
|
|
- def skip_test_perform_get_with_default_write_function(self):
|
|
+ def skip_perform_get_with_default_write_function(self):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/success')
|
|
with tempfile.NamedTemporaryFile() as f:
|
|
#with open('w', 'w+') as f:
|
|
diff --git a/tests/reset_test.py b/tests/reset_test.py
|
|
index 66b7108..cc55f86 100644
|
|
--- a/tests/reset_test.py
|
|
+++ b/tests/reset_test.py
|
|
@@ -18,7 +18,7 @@ setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
class ResetTest(unittest.TestCase):
|
|
# XXX this test was broken when it was test_reset.py
|
|
- def skip_test_reset(self):
|
|
+ def skip_reset(self):
|
|
outf = util.StringIO()
|
|
cm = pycurl.CurlMulti()
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d3a77eabe019b1707a7bdf8cbae32d1eddd12f9c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 01:29:59 -0500
|
|
Subject: [PATCH 056/149] Store urlencode result in a local variable, otherwise things break in a highly weird way
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/post_test.py | 24 +++++++++++++++++++++++-
|
|
1 files changed, 23 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index 564d043..e8b0675 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -40,11 +40,33 @@ class PostTest(unittest.TestCase):
|
|
|
|
def urlencode_and_check(self, pf):
|
|
self.curl.setopt(pycurl.URL, 'http://localhost:8380/postfields')
|
|
- self.curl.setopt(pycurl.POSTFIELDS, urllib_parse.urlencode(pf))
|
|
+ postfields = urllib_parse.urlencode(pf)
|
|
+ self.curl.setopt(pycurl.POSTFIELDS, postfields)
|
|
+
|
|
+ # But directly passing urlencode result into setopt call:
|
|
+ #self.curl.setopt(pycurl.POSTFIELDS, urllib_parse.urlencode(pf))
|
|
+ # produces:
|
|
+ # {'\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00': ''}
|
|
+ # Traceback (most recent call last):
|
|
+ # File "/usr/local/bin/bottle.py", line 744, in _handle
|
|
+ # return route.call(**args)
|
|
+ # File "/usr/local/bin/bottle.py", line 1479, in wrapper
|
|
+ # rv = callback(*a, **ka)
|
|
+ # File "/home/pie/apps/pycurl/tests/app.py", line 21, in postfields
|
|
+ # return json.dumps(dict(bottle.request.forms))
|
|
+ # File "/usr/local/lib/python2.7/json/__init__.py", line 231, in dumps
|
|
+ # return _default_encoder.encode(obj)
|
|
+ # File "/usr/local/lib/python2.7/json/encoder.py", line 201, in encode
|
|
+ # chunks = self.iterencode(o, _one_shot=True)
|
|
+ # File "/usr/local/lib/python2.7/json/encoder.py", line 264, in iterencode
|
|
+ # return _iterencode(o, 0)
|
|
+ # UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 4: invalid start byte
|
|
+
|
|
#self.curl.setopt(pycurl.VERBOSE, 1)
|
|
sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.perform()
|
|
+ self.assertEqual(200, self.curl.getinfo(pycurl.HTTP_CODE))
|
|
body = sio.getvalue()
|
|
returned_fields = json.loads(body)
|
|
self.assertEqual(pf, returned_fields)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 3ea332ffec21dfe6ddf3e0bc66a101259f88f216 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 01:32:33 -0500
|
|
Subject: [PATCH 057/149] Fix regular expression to allow all hex chars like it should
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/internals_test.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/internals_test.py b/tests/internals_test.py
|
|
index fb451df..f628ab2 100644
|
|
--- a/tests/internals_test.py
|
|
+++ b/tests/internals_test.py
|
|
@@ -180,7 +180,7 @@ class InternalsTest(unittest.TestCase):
|
|
del m, c
|
|
|
|
def test_cyclic_gc(self):
|
|
- regexp = re.compile(r'at (0x\d+)')
|
|
+ regexp = re.compile(r'at (0x[\da-f]+)')
|
|
gc.collect()
|
|
c = pycurl.Curl()
|
|
c.m = pycurl.CurlMulti()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 990569ee36eac37c03f28c86b2a8cfc7a29752ab Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 01:36:48 -0500
|
|
Subject: [PATCH 058/149] Rewrite cyclic gc test to use id()
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/internals_test.py | 9 ++-------
|
|
1 files changed, 2 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/tests/internals_test.py b/tests/internals_test.py
|
|
index f628ab2..0133da0 100644
|
|
--- a/tests/internals_test.py
|
|
+++ b/tests/internals_test.py
|
|
@@ -12,7 +12,6 @@ except ImportError:
|
|
import pickle
|
|
import gc
|
|
import copy
|
|
-import re
|
|
|
|
class InternalsTest(unittest.TestCase):
|
|
def setUp(self):
|
|
@@ -180,7 +179,6 @@ class InternalsTest(unittest.TestCase):
|
|
del m, c
|
|
|
|
def test_cyclic_gc(self):
|
|
- regexp = re.compile(r'at (0x[\da-f]+)')
|
|
gc.collect()
|
|
c = pycurl.Curl()
|
|
c.m = pycurl.CurlMulti()
|
|
@@ -208,17 +206,14 @@ class InternalsTest(unittest.TestCase):
|
|
##print gc.get_objects()
|
|
#if opts.verbose >= 1:
|
|
#print("Tracked objects:", len(gc.get_objects()))
|
|
- match = regexp.search(repr(c))
|
|
- assert match is not None
|
|
- address = match.group(1)
|
|
+ c_id = id(c)
|
|
# The `del' below should delete these 4 objects:
|
|
# Curl + internal dict, CurlMulti + internal dict
|
|
del c
|
|
gc.collect()
|
|
objects = gc.get_objects()
|
|
- search = 'at %s' % address
|
|
for object in objects:
|
|
- assert search not in repr(object)
|
|
+ assert id(object) != c_id
|
|
#if opts.verbose >= 1:
|
|
#print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 3b7bb39d6b33031ff1efd03abdc174caa32ef3bc Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 03:25:34 -0500
|
|
Subject: [PATCH 059/149] Adjust ftp test to work with vsftpd started from project root
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/ftp_test.py | 18 ++++++++++--------
|
|
1 files changed, 10 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/tests/ftp_test.py b/tests/ftp_test.py
|
|
index d215b6e..1d382ed 100644
|
|
--- a/tests/ftp_test.py
|
|
+++ b/tests/ftp_test.py
|
|
@@ -2,6 +2,8 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
+# Note: this test is meant to be run from pycurl project root.
|
|
+
|
|
import pycurl
|
|
import unittest
|
|
|
|
@@ -15,29 +17,29 @@ class FtpTest(unittest.TestCase):
|
|
self.curl.close()
|
|
|
|
def test_get_ftp(self):
|
|
- self.curl.setopt(pycurl.URL, 'ftp://localhost:8921')
|
|
+ self.curl.setopt(pycurl.URL, 'ftp://localhost:8321')
|
|
sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.perform()
|
|
|
|
result = sio.getvalue()
|
|
assert 'README' in result
|
|
- assert 'bin -> usr/bin' in result
|
|
+ assert 'INSTALL' in result
|
|
|
|
# XXX this test needs to be fixed
|
|
def test_quote(self):
|
|
- self.curl.setopt(pycurl.URL, 'ftp://localhost:8921')
|
|
+ self.curl.setopt(pycurl.URL, 'ftp://localhost:8321')
|
|
sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
- self.curl.setopt(pycurl.QUOTE, ['CWD pub'])
|
|
+ self.curl.setopt(pycurl.QUOTE, ['CWD tests'])
|
|
self.curl.perform()
|
|
|
|
result = sio.getvalue()
|
|
- assert 'README' in result
|
|
- assert 'bin -> usr/bin' in result
|
|
+ assert 'README' not in result
|
|
+ assert 'ftp_test.py' in result
|
|
|
|
def test_epsv(self):
|
|
- self.curl.setopt(pycurl.URL, 'ftp://localhost:8921')
|
|
+ self.curl.setopt(pycurl.URL, 'ftp://localhost:8321')
|
|
sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.setopt(pycurl.FTP_USE_EPSV, 1)
|
|
@@ -45,4 +47,4 @@ class FtpTest(unittest.TestCase):
|
|
|
|
result = sio.getvalue()
|
|
assert 'README' in result
|
|
- assert 'bin -> usr/bin' in result
|
|
+ assert 'INSTALL' in result
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From ce0c221f9db95029982619afd5cc154d68a97334 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:01:13 -0500
|
|
Subject: [PATCH 060/149] Execute vsftpd as test ftp server
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/ftp_test.py | 3 ++
|
|
tests/procmgr.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
tests/runwsgi.py | 20 ++++++++------
|
|
tests/vsftpd.conf | 10 +++++++
|
|
4 files changed, 98 insertions(+), 8 deletions(-)
|
|
create mode 100644 tests/procmgr.py
|
|
create mode 100644 tests/vsftpd.conf
|
|
|
|
diff --git a/tests/ftp_test.py b/tests/ftp_test.py
|
|
index 1d382ed..fa2ef79 100644
|
|
--- a/tests/ftp_test.py
|
|
+++ b/tests/ftp_test.py
|
|
@@ -8,6 +8,9 @@ import pycurl
|
|
import unittest
|
|
|
|
from . import util
|
|
+from . import procmgr
|
|
+
|
|
+setup_module, teardown_module = procmgr.vsftpd_setup()
|
|
|
|
class FtpTest(unittest.TestCase):
|
|
def setUp(self):
|
|
diff --git a/tests/procmgr.py b/tests/procmgr.py
|
|
new file mode 100644
|
|
index 0000000..8d5c0cc
|
|
--- /dev/null
|
|
+++ b/tests/procmgr.py
|
|
@@ -0,0 +1,73 @@
|
|
+import threading
|
|
+import subprocess
|
|
+import os
|
|
+import signal
|
|
+
|
|
+from . import runwsgi
|
|
+
|
|
+class ProcessManager(object):
|
|
+ def __init__(self, cmd):
|
|
+ self.cmd = cmd
|
|
+
|
|
+ def start(self):
|
|
+ self.process = subprocess.Popen(self.cmd)
|
|
+
|
|
+ self.thread = threading.Thread(target=self.run)
|
|
+ self.thread.daemon = True
|
|
+ self.thread.start()
|
|
+
|
|
+ def run(self):
|
|
+ self.process.communicate()
|
|
+
|
|
+managers = {}
|
|
+
|
|
+def start(cmd):
|
|
+ if str(cmd) in managers:
|
|
+ # already started
|
|
+ return
|
|
+
|
|
+ manager = ProcessManager(cmd)
|
|
+ managers[str(cmd)] = manager
|
|
+ manager.start()
|
|
+
|
|
+def start_setup(cmd):
|
|
+ def do_start():
|
|
+ start(cmd)
|
|
+ return do_start
|
|
+
|
|
+# Example on FreeBSD:
|
|
+# PYCURL_VSFTPD_PATH=/usr/local/libexec/vsftpd nosetests
|
|
+
|
|
+if 'PYCURL_VSFTPD_PATH' in os.environ:
|
|
+ vsftpd_path = os.environ['PYCURL_VSFTPD_PATH']
|
|
+else:
|
|
+ vsftpd_path = 'vsftpd'
|
|
+
|
|
+def vsftpd_setup():
|
|
+ config_file_path = os.path.join(os.path.dirname(__file__), 'vsftpd.conf')
|
|
+ root_path = os.path.join(os.path.dirname(__file__), '..')
|
|
+ cmd = [
|
|
+ vsftpd_path,
|
|
+ config_file_path,
|
|
+ '-oanon_root=%s' % root_path,
|
|
+ ]
|
|
+ setup_module = start_setup(cmd)
|
|
+ def do_setup_module():
|
|
+ setup_module()
|
|
+ ok = runwsgi.wait_for_network_service(('127.0.0.1', 8321), 0.1, 10)
|
|
+ if not ok:
|
|
+ import warnings
|
|
+ warnings.warn('vsftpd did not start after 1 second')
|
|
+
|
|
+ def teardown_module():
|
|
+ try:
|
|
+ manager = managers[str(cmd)]
|
|
+ except KeyError:
|
|
+ pass
|
|
+ else:
|
|
+ try:
|
|
+ os.kill(manager.process.pid, signal.SIGTERM)
|
|
+ except OSError:
|
|
+ pass
|
|
+
|
|
+ return do_setup_module, teardown_module
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index 6d3b69f..5217a3f 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -16,21 +16,25 @@ class Server(bottle.WSGIRefServer):
|
|
self.srv = make_server(self.host, self.port, handler, **self.options)
|
|
self.srv.serve_forever(poll_interval=0.1)
|
|
|
|
-def start_bottle_server(app, port, **kwargs):
|
|
- server_thread = ServerThread(app, port, kwargs)
|
|
- server_thread.daemon = True
|
|
- server_thread.start()
|
|
-
|
|
+def wait_for_network_service(netloc, check_interval, num_attempts):
|
|
ok = False
|
|
- for i in range(10):
|
|
+ for i in range(num_attempts):
|
|
try:
|
|
- conn = socket.create_connection(('127.0.0.1', port), 0.1)
|
|
+ conn = socket.create_connection(netloc, check_interval)
|
|
except socket.error as e:
|
|
- _time.sleep(0.1)
|
|
+ _time.sleep(check_interval)
|
|
else:
|
|
conn.close()
|
|
ok = True
|
|
break
|
|
+ return ok
|
|
+
|
|
+def start_bottle_server(app, port, **kwargs):
|
|
+ server_thread = ServerThread(app, port, kwargs)
|
|
+ server_thread.daemon = True
|
|
+ server_thread.start()
|
|
+
|
|
+ ok = wait_for_network_service(('127.0.0.1', port), 0.1, 10)
|
|
if not ok:
|
|
import warnings
|
|
warnings.warn('Server did not start after 1 second')
|
|
diff --git a/tests/vsftpd.conf b/tests/vsftpd.conf
|
|
new file mode 100644
|
|
index 0000000..0abb39f
|
|
--- /dev/null
|
|
+++ b/tests/vsftpd.conf
|
|
@@ -0,0 +1,10 @@
|
|
+anon_world_readable_only=yes
|
|
+anonymous_enable=yes
|
|
+# currently we only list files
|
|
+download_enable=no
|
|
+listen=yes
|
|
+run_as_launching_user=yes
|
|
+write_enable=no
|
|
+listen_port=8321
|
|
+# should be supplied on command line
|
|
+anon_root=/var/empty
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 0457d78a5bd77c11ac67698f125c596f16f05da6 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:37:19 -0500
|
|
Subject: [PATCH 061/149] Move gtk and xmlrpc tests to examples as they do not test anything not already tested by the test suite
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
examples/tests/test_gtk.py | 98 +++++++++++++++++++++++++++++++++++++++++
|
|
examples/tests/test_xmlrpc.py | 29 ++++++++++++
|
|
tests/test_gtk.py | 98 -----------------------------------------
|
|
tests/test_xmlrpc.py | 29 ------------
|
|
4 files changed, 127 insertions(+), 127 deletions(-)
|
|
create mode 100644 examples/tests/test_gtk.py
|
|
create mode 100644 examples/tests/test_xmlrpc.py
|
|
delete mode 100644 tests/test_gtk.py
|
|
delete mode 100644 tests/test_xmlrpc.py
|
|
|
|
diff --git a/examples/tests/test_gtk.py b/examples/tests/test_gtk.py
|
|
new file mode 100644
|
|
index 0000000..7104439
|
|
--- /dev/null
|
|
+++ b/examples/tests/test_gtk.py
|
|
@@ -0,0 +1,98 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+# $Id$
|
|
+
|
|
+import sys, threading
|
|
+import pycurl
|
|
+import pygtk
|
|
+pygtk.require('2.0')
|
|
+import gtk
|
|
+
|
|
+# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
|
|
+# the libcurl tutorial for more info.
|
|
+try:
|
|
+ import signal
|
|
+ from signal import SIGPIPE, SIG_IGN
|
|
+ signal.signal(signal.SIGPIPE, signal.SIG_IGN)
|
|
+except ImportError:
|
|
+ pass
|
|
+
|
|
+
|
|
+class ProgressBar:
|
|
+ def __init__(self, uri):
|
|
+ self.round = 0.0
|
|
+ win = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
|
+ win.set_title("PycURL progress")
|
|
+ win.show()
|
|
+ vbox = gtk.VBox(spacing=5)
|
|
+ vbox.set_border_width(10)
|
|
+ win.add(vbox)
|
|
+ win.set_default_size(200, 20)
|
|
+ vbox.show()
|
|
+ label = gtk.Label("Downloading %s" % uri)
|
|
+ label.set_alignment(0, 0.5)
|
|
+ vbox.pack_start(label)
|
|
+ label.show()
|
|
+ pbar = gtk.ProgressBar()
|
|
+ pbar.show()
|
|
+ self.pbar = pbar
|
|
+ vbox.pack_start(pbar)
|
|
+ win.connect("destroy", self.close_app)
|
|
+
|
|
+ def progress(self, download_t, download_d, upload_t, upload_d):
|
|
+ if download_t == 0:
|
|
+ self.round = self.round + 0.1
|
|
+ if self.round >= 1.0: self.round = 0.0
|
|
+ else:
|
|
+ self.round = float(download_d) / float(download_t)
|
|
+ gtk.threads_enter()
|
|
+ self.pbar.set_fraction(self.round)
|
|
+ gtk.threads_leave()
|
|
+
|
|
+ def mainloop(self):
|
|
+ gtk.threads_enter()
|
|
+ gtk.main()
|
|
+ gtk.threads_leave()
|
|
+
|
|
+ def close_app(self, *args):
|
|
+ args[0].destroy()
|
|
+ gtk.main_quit()
|
|
+
|
|
+
|
|
+class Test(threading.Thread):
|
|
+ def __init__(self, url, target_file, progress):
|
|
+ threading.Thread.__init__(self)
|
|
+ self.target_file = target_file
|
|
+ self.progress = progress
|
|
+ self.curl = pycurl.Curl()
|
|
+ self.curl.setopt(pycurl.URL, url)
|
|
+ self.curl.setopt(pycurl.WRITEDATA, self.target_file)
|
|
+ self.curl.setopt(pycurl.FOLLOWLOCATION, 1)
|
|
+ self.curl.setopt(pycurl.NOPROGRESS, 0)
|
|
+ self.curl.setopt(pycurl.PROGRESSFUNCTION, self.progress)
|
|
+ self.curl.setopt(pycurl.MAXREDIRS, 5)
|
|
+ self.curl.setopt(pycurl.NOSIGNAL, 1)
|
|
+
|
|
+ def run(self):
|
|
+ self.curl.perform()
|
|
+ self.curl.close()
|
|
+ self.target_file.close()
|
|
+ self.progress(1.0, 1.0, 0, 0)
|
|
+
|
|
+
|
|
+# Check command line args
|
|
+if len(sys.argv) < 3:
|
|
+ print "Usage: %s <URL> <filename>" % sys.argv[0]
|
|
+ raise SystemExit
|
|
+
|
|
+# Make a progress bar window
|
|
+p = ProgressBar(sys.argv[1])
|
|
+# Start thread for fetching url
|
|
+Test(sys.argv[1], open(sys.argv[2], 'wb'), p.progress).start()
|
|
+# Enter the GTK mainloop
|
|
+gtk.threads_init()
|
|
+try:
|
|
+ p.mainloop()
|
|
+except KeyboardInterrupt:
|
|
+ pass
|
|
diff --git a/examples/tests/test_xmlrpc.py b/examples/tests/test_xmlrpc.py
|
|
new file mode 100644
|
|
index 0000000..bc5953e
|
|
--- /dev/null
|
|
+++ b/examples/tests/test_xmlrpc.py
|
|
@@ -0,0 +1,29 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+# $Id$
|
|
+
|
|
+## XML-RPC lib included in python2.2
|
|
+import xmlrpclib
|
|
+import pycurl
|
|
+
|
|
+# Header fields passed in request
|
|
+xmlrpc_header = [
|
|
+ "User-Agent: PycURL XML-RPC Test", "Content-Type: text/xml"
|
|
+ ]
|
|
+
|
|
+# XML-RPC request template
|
|
+xmlrpc_template = """
|
|
+<?xml version='1.0'?><methodCall><methodName>%s</methodName>%s</methodCall>
|
|
+"""
|
|
+
|
|
+# Engage
|
|
+c = pycurl.Curl()
|
|
+c.setopt(c.URL, 'http://betty.userland.com/RPC2')
|
|
+c.setopt(c.POST, 1)
|
|
+c.setopt(c.HTTPHEADER, xmlrpc_header)
|
|
+c.setopt(c.POSTFIELDS, xmlrpc_template % ("examples.getStateName", xmlrpclib.dumps((5,))))
|
|
+
|
|
+print 'Response from http://betty.userland.com/'
|
|
+c.perform()
|
|
+c.close()
|
|
diff --git a/tests/test_gtk.py b/tests/test_gtk.py
|
|
deleted file mode 100644
|
|
index 7104439..0000000
|
|
--- a/tests/test_gtk.py
|
|
+++ /dev/null
|
|
@@ -1,98 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys, threading
|
|
-import pycurl
|
|
-import pygtk
|
|
-pygtk.require('2.0')
|
|
-import gtk
|
|
-
|
|
-# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
|
|
-# the libcurl tutorial for more info.
|
|
-try:
|
|
- import signal
|
|
- from signal import SIGPIPE, SIG_IGN
|
|
- signal.signal(signal.SIGPIPE, signal.SIG_IGN)
|
|
-except ImportError:
|
|
- pass
|
|
-
|
|
-
|
|
-class ProgressBar:
|
|
- def __init__(self, uri):
|
|
- self.round = 0.0
|
|
- win = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
|
- win.set_title("PycURL progress")
|
|
- win.show()
|
|
- vbox = gtk.VBox(spacing=5)
|
|
- vbox.set_border_width(10)
|
|
- win.add(vbox)
|
|
- win.set_default_size(200, 20)
|
|
- vbox.show()
|
|
- label = gtk.Label("Downloading %s" % uri)
|
|
- label.set_alignment(0, 0.5)
|
|
- vbox.pack_start(label)
|
|
- label.show()
|
|
- pbar = gtk.ProgressBar()
|
|
- pbar.show()
|
|
- self.pbar = pbar
|
|
- vbox.pack_start(pbar)
|
|
- win.connect("destroy", self.close_app)
|
|
-
|
|
- def progress(self, download_t, download_d, upload_t, upload_d):
|
|
- if download_t == 0:
|
|
- self.round = self.round + 0.1
|
|
- if self.round >= 1.0: self.round = 0.0
|
|
- else:
|
|
- self.round = float(download_d) / float(download_t)
|
|
- gtk.threads_enter()
|
|
- self.pbar.set_fraction(self.round)
|
|
- gtk.threads_leave()
|
|
-
|
|
- def mainloop(self):
|
|
- gtk.threads_enter()
|
|
- gtk.main()
|
|
- gtk.threads_leave()
|
|
-
|
|
- def close_app(self, *args):
|
|
- args[0].destroy()
|
|
- gtk.main_quit()
|
|
-
|
|
-
|
|
-class Test(threading.Thread):
|
|
- def __init__(self, url, target_file, progress):
|
|
- threading.Thread.__init__(self)
|
|
- self.target_file = target_file
|
|
- self.progress = progress
|
|
- self.curl = pycurl.Curl()
|
|
- self.curl.setopt(pycurl.URL, url)
|
|
- self.curl.setopt(pycurl.WRITEDATA, self.target_file)
|
|
- self.curl.setopt(pycurl.FOLLOWLOCATION, 1)
|
|
- self.curl.setopt(pycurl.NOPROGRESS, 0)
|
|
- self.curl.setopt(pycurl.PROGRESSFUNCTION, self.progress)
|
|
- self.curl.setopt(pycurl.MAXREDIRS, 5)
|
|
- self.curl.setopt(pycurl.NOSIGNAL, 1)
|
|
-
|
|
- def run(self):
|
|
- self.curl.perform()
|
|
- self.curl.close()
|
|
- self.target_file.close()
|
|
- self.progress(1.0, 1.0, 0, 0)
|
|
-
|
|
-
|
|
-# Check command line args
|
|
-if len(sys.argv) < 3:
|
|
- print "Usage: %s <URL> <filename>" % sys.argv[0]
|
|
- raise SystemExit
|
|
-
|
|
-# Make a progress bar window
|
|
-p = ProgressBar(sys.argv[1])
|
|
-# Start thread for fetching url
|
|
-Test(sys.argv[1], open(sys.argv[2], 'wb'), p.progress).start()
|
|
-# Enter the GTK mainloop
|
|
-gtk.threads_init()
|
|
-try:
|
|
- p.mainloop()
|
|
-except KeyboardInterrupt:
|
|
- pass
|
|
diff --git a/tests/test_xmlrpc.py b/tests/test_xmlrpc.py
|
|
deleted file mode 100644
|
|
index bc5953e..0000000
|
|
--- a/tests/test_xmlrpc.py
|
|
+++ /dev/null
|
|
@@ -1,29 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-## XML-RPC lib included in python2.2
|
|
-import xmlrpclib
|
|
-import pycurl
|
|
-
|
|
-# Header fields passed in request
|
|
-xmlrpc_header = [
|
|
- "User-Agent: PycURL XML-RPC Test", "Content-Type: text/xml"
|
|
- ]
|
|
-
|
|
-# XML-RPC request template
|
|
-xmlrpc_template = """
|
|
-<?xml version='1.0'?><methodCall><methodName>%s</methodName>%s</methodCall>
|
|
-"""
|
|
-
|
|
-# Engage
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, 'http://betty.userland.com/RPC2')
|
|
-c.setopt(c.POST, 1)
|
|
-c.setopt(c.HTTPHEADER, xmlrpc_header)
|
|
-c.setopt(c.POSTFIELDS, xmlrpc_template % ("examples.getStateName", xmlrpclib.dumps((5,))))
|
|
-
|
|
-print 'Response from http://betty.userland.com/'
|
|
-c.perform()
|
|
-c.close()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 25e7d646b9d5c80e8987528bf1b0031622ab440b Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 00:37:41 -0500
|
|
Subject: [PATCH 062/149] Delete old tests
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/test.py | 74 -----------
|
|
tests/test_cb.py | 28 ----
|
|
tests/test_debug.py | 16 ---
|
|
tests/test_ftp.py | 13 --
|
|
tests/test_getinfo.py | 49 -------
|
|
tests/test_internals.py | 258 ------------------------------------
|
|
tests/test_memleak.py | 53 --------
|
|
tests/test_multi.py | 33 -----
|
|
tests/test_multi2.py | 72 ----------
|
|
tests/test_multi3.py | 87 ------------
|
|
tests/test_multi4.py | 57 --------
|
|
tests/test_multi5.py | 60 ---------
|
|
tests/test_multi6.py | 62 ---------
|
|
tests/test_multi_socket.py | 82 ------------
|
|
tests/test_multi_socket_select.py | 105 ---------------
|
|
tests/test_multi_timer.py | 76 -----------
|
|
tests/test_multi_vs_thread.py | 262 -------------------------------------
|
|
tests/test_post.py | 24 ----
|
|
tests/test_post2.py | 18 ---
|
|
tests/test_post3.py | 32 -----
|
|
tests/test_reset.py | 75 -----------
|
|
tests/test_share.py | 34 -----
|
|
tests/test_socketopen.py | 17 ---
|
|
tests/test_stringio.py | 25 ----
|
|
24 files changed, 0 insertions(+), 1612 deletions(-)
|
|
delete mode 100644 tests/test.py
|
|
delete mode 100644 tests/test_cb.py
|
|
delete mode 100644 tests/test_debug.py
|
|
delete mode 100644 tests/test_ftp.py
|
|
delete mode 100644 tests/test_getinfo.py
|
|
delete mode 100644 tests/test_internals.py
|
|
delete mode 100644 tests/test_memleak.py
|
|
delete mode 100644 tests/test_multi.py
|
|
delete mode 100644 tests/test_multi2.py
|
|
delete mode 100644 tests/test_multi3.py
|
|
delete mode 100644 tests/test_multi4.py
|
|
delete mode 100644 tests/test_multi5.py
|
|
delete mode 100644 tests/test_multi6.py
|
|
delete mode 100644 tests/test_multi_socket.py
|
|
delete mode 100644 tests/test_multi_socket_select.py
|
|
delete mode 100644 tests/test_multi_timer.py
|
|
delete mode 100644 tests/test_multi_vs_thread.py
|
|
delete mode 100644 tests/test_post.py
|
|
delete mode 100644 tests/test_post2.py
|
|
delete mode 100644 tests/test_post3.py
|
|
delete mode 100644 tests/test_reset.py
|
|
delete mode 100644 tests/test_share.py
|
|
delete mode 100644 tests/test_socketopen.py
|
|
delete mode 100644 tests/test_stringio.py
|
|
|
|
diff --git a/tests/test.py b/tests/test.py
|
|
deleted file mode 100644
|
|
index 5cd9740..0000000
|
|
--- a/tests/test.py
|
|
+++ /dev/null
|
|
@@ -1,74 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys, threading, time
|
|
-import pycurl
|
|
-
|
|
-# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
|
|
-# the libcurl tutorial for more info.
|
|
-try:
|
|
- import signal
|
|
- from signal import SIGPIPE, SIG_IGN
|
|
- signal.signal(signal.SIGPIPE, signal.SIG_IGN)
|
|
-except ImportError:
|
|
- pass
|
|
-
|
|
-
|
|
-class Test(threading.Thread):
|
|
- def __init__(self, url, ofile):
|
|
- threading.Thread.__init__(self)
|
|
- self.curl = pycurl.Curl()
|
|
- self.curl.setopt(pycurl.URL, url)
|
|
- self.curl.setopt(pycurl.WRITEDATA, ofile)
|
|
- self.curl.setopt(pycurl.FOLLOWLOCATION, 1)
|
|
- self.curl.setopt(pycurl.MAXREDIRS, 5)
|
|
- self.curl.setopt(pycurl.NOSIGNAL, 1)
|
|
-
|
|
- def run(self):
|
|
- self.curl.perform()
|
|
- self.curl.close()
|
|
- sys.stdout.write(".")
|
|
- sys.stdout.flush()
|
|
-
|
|
-
|
|
-# Read list of URIs from file specified on commandline
|
|
-try:
|
|
- urls = open(sys.argv[1]).readlines()
|
|
-except IndexError:
|
|
- # No file was specified, show usage string
|
|
- print "Usage: %s <file with uris to fetch>" % sys.argv[0]
|
|
- raise SystemExit
|
|
-
|
|
-# Initialize thread array and the file number
|
|
-threads = []
|
|
-fileno = 0
|
|
-
|
|
-# Start one thread per URI in parallel
|
|
-t1 = time.time()
|
|
-for url in urls:
|
|
- f = open(str(fileno), "wb")
|
|
- t = Test(url.rstrip(), f)
|
|
- t.start()
|
|
- threads.append((t, f))
|
|
- fileno = fileno + 1
|
|
-# Wait for all threads to finish
|
|
-for thread, file in threads:
|
|
- thread.join()
|
|
- file.close()
|
|
-t2 = time.time()
|
|
-print "\n** Multithreading, %d seconds elapsed for %d uris" % (int(t2-t1), len(urls))
|
|
-
|
|
-# Start one thread per URI in sequence
|
|
-fileno = 0
|
|
-t1 = time.time()
|
|
-for url in urls:
|
|
- f = open(str(fileno), "wb")
|
|
- t = Test(url.rstrip(), f)
|
|
- t.start()
|
|
- fileno = fileno + 1
|
|
- t.join()
|
|
- f.close()
|
|
-t2 = time.time()
|
|
-print "\n** Singlethreading, %d seconds elapsed for %d uris" % (int(t2-t1), len(urls))
|
|
diff --git a/tests/test_cb.py b/tests/test_cb.py
|
|
deleted file mode 100644
|
|
index 1be305c..0000000
|
|
--- a/tests/test_cb.py
|
|
+++ /dev/null
|
|
@@ -1,28 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys
|
|
-import pycurl
|
|
-
|
|
-## Callback function invoked when body data is ready
|
|
-def body(buf):
|
|
- # Print body data to stdout
|
|
- sys.stdout.write(buf)
|
|
-
|
|
-## Callback function invoked when header data is ready
|
|
-def header(buf):
|
|
- # Print header data to stderr
|
|
- sys.stderr.write(buf)
|
|
-
|
|
-c = pycurl.Curl()
|
|
-c.setopt(pycurl.URL, 'http://www.python.org/')
|
|
-c.setopt(pycurl.WRITEFUNCTION, body)
|
|
-c.setopt(pycurl.HEADERFUNCTION, header)
|
|
-c.setopt(pycurl.FOLLOWLOCATION, 1)
|
|
-c.setopt(pycurl.MAXREDIRS, 5)
|
|
-c.perform()
|
|
-c.setopt(pycurl.URL, 'http://curl.haxx.se/')
|
|
-c.perform()
|
|
-c.close()
|
|
diff --git a/tests/test_debug.py b/tests/test_debug.py
|
|
deleted file mode 100644
|
|
index d439b16..0000000
|
|
--- a/tests/test_debug.py
|
|
+++ /dev/null
|
|
@@ -1,16 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import pycurl
|
|
-
|
|
-def test(t, b):
|
|
- print "debug(%d): %s" % (t, b)
|
|
-
|
|
-c = pycurl.Curl()
|
|
-c.setopt(pycurl.URL, 'http://curl.haxx.se/')
|
|
-c.setopt(pycurl.VERBOSE, 1)
|
|
-c.setopt(pycurl.DEBUGFUNCTION, test)
|
|
-c.perform()
|
|
-c.close()
|
|
diff --git a/tests/test_ftp.py b/tests/test_ftp.py
|
|
deleted file mode 100644
|
|
index 2d4d358..0000000
|
|
--- a/tests/test_ftp.py
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import pycurl
|
|
-
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, 'ftp://ftp.sunet.se/')
|
|
-c.setopt(c.FTP_USE_EPSV, 1)
|
|
-c.setopt(c.QUOTE, ['cwd pub', 'type i'])
|
|
-c.perform()
|
|
-c.close()
|
|
diff --git a/tests/test_getinfo.py b/tests/test_getinfo.py
|
|
deleted file mode 100644
|
|
index ed64594..0000000
|
|
--- a/tests/test_getinfo.py
|
|
+++ /dev/null
|
|
@@ -1,49 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import time
|
|
-import pycurl
|
|
-
|
|
-
|
|
-## Callback function invoked when progress information is updated
|
|
-def progress(download_t, download_d, upload_t, upload_d):
|
|
- print "Total to download %d bytes, have %d bytes so far" % \
|
|
- (download_t, download_d)
|
|
-
|
|
-url = "http://www.cnn.com"
|
|
-
|
|
-print "Starting downloading", url
|
|
-print
|
|
-f = open("body", "wb")
|
|
-h = open("header", "wb")
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, url)
|
|
-c.setopt(c.WRITEDATA, f)
|
|
-c.setopt(c.NOPROGRESS, 0)
|
|
-c.setopt(c.PROGRESSFUNCTION, progress)
|
|
-c.setopt(c.FOLLOWLOCATION, 1)
|
|
-c.setopt(c.MAXREDIRS, 5)
|
|
-c.setopt(c.WRITEHEADER, h)
|
|
-c.setopt(c.OPT_FILETIME, 1)
|
|
-c.perform()
|
|
-
|
|
-print
|
|
-print "HTTP-code:", c.getinfo(c.HTTP_CODE)
|
|
-print "Total-time:", c.getinfo(c.TOTAL_TIME)
|
|
-print "Download speed: %.2f bytes/second" % c.getinfo(c.SPEED_DOWNLOAD)
|
|
-print "Document size: %d bytes" % c.getinfo(c.SIZE_DOWNLOAD)
|
|
-print "Effective URL:", c.getinfo(c.EFFECTIVE_URL)
|
|
-print "Content-type:", c.getinfo(c.CONTENT_TYPE)
|
|
-print "Namelookup-time:", c.getinfo(c.NAMELOOKUP_TIME)
|
|
-print "Redirect-time:", c.getinfo(c.REDIRECT_TIME)
|
|
-print "Redirect-count:", c.getinfo(c.REDIRECT_COUNT)
|
|
-epoch = c.getinfo(c.INFO_FILETIME)
|
|
-print "Filetime: %d (%s)" % (epoch, time.ctime(epoch))
|
|
-print
|
|
-print "Header is in file 'header', body is in file 'body'"
|
|
-
|
|
-c.close()
|
|
-f.close()
|
|
-h.close()
|
|
diff --git a/tests/test_internals.py b/tests/test_internals.py
|
|
deleted file mode 100644
|
|
index 3f5eefd..0000000
|
|
--- a/tests/test_internals.py
|
|
+++ /dev/null
|
|
@@ -1,258 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-#
|
|
-# a simple self-test
|
|
-#
|
|
-
|
|
-try:
|
|
- # need Python 2.2 or better for garbage collection
|
|
- from gc import get_objects
|
|
- import gc
|
|
- del get_objects
|
|
- gc.enable()
|
|
-except ImportError:
|
|
- gc = None
|
|
-import copy, os, sys
|
|
-from StringIO import StringIO
|
|
-try:
|
|
- import cPickle
|
|
-except ImportError:
|
|
- cPickle = None
|
|
-try:
|
|
- import pickle
|
|
-except ImportError:
|
|
- pickle = None
|
|
-
|
|
-# update sys.path when running in the build directory
|
|
-from util import get_sys_path
|
|
-sys.path = get_sys_path()
|
|
-
|
|
-import pycurl
|
|
-from pycurl import Curl, CurlMulti
|
|
-
|
|
-
|
|
-class opts:
|
|
- verbose = 1
|
|
-
|
|
-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)
|
|
-
|
|
-
|
|
-# /***********************************************************************
|
|
-# // test misc
|
|
-# ************************************************************************/
|
|
-
|
|
-if 1:
|
|
- c = Curl()
|
|
- assert c.URL is pycurl.URL
|
|
- del c
|
|
-
|
|
-
|
|
-# /***********************************************************************
|
|
-# // test handles
|
|
-# ************************************************************************/
|
|
-
|
|
-# remove an invalid handle: this should fail
|
|
-if 1:
|
|
- m = CurlMulti()
|
|
- c = Curl()
|
|
- try:
|
|
- m.remove_handle(c)
|
|
- except pycurl.error:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error"
|
|
- del m, c
|
|
-
|
|
-
|
|
-# remove an invalid but closed handle
|
|
-if 1:
|
|
- m = CurlMulti()
|
|
- c = Curl()
|
|
- c.close()
|
|
- m.remove_handle(c)
|
|
- del m, c
|
|
-
|
|
-
|
|
-# add a closed handle: this should fail
|
|
-if 1:
|
|
- m = CurlMulti()
|
|
- c = Curl()
|
|
- c.close()
|
|
- try:
|
|
- m.add_handle(c)
|
|
- except pycurl.error:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error"
|
|
- m.close()
|
|
- del m, c
|
|
-
|
|
-
|
|
-# add a handle twice: this should fail
|
|
-if 1:
|
|
- m = CurlMulti()
|
|
- c = Curl()
|
|
- m.add_handle(c)
|
|
- try:
|
|
- m.add_handle(c)
|
|
- except pycurl.error:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error"
|
|
- del m, c
|
|
-
|
|
-
|
|
-# add a handle on multiple stacks: this should fail
|
|
-if 1:
|
|
- m1 = CurlMulti()
|
|
- m2 = CurlMulti()
|
|
- c = Curl()
|
|
- m1.add_handle(c)
|
|
- try:
|
|
- m2.add_handle(c)
|
|
- except pycurl.error:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error"
|
|
- del m1, m2, c
|
|
-
|
|
-
|
|
-# move a handle
|
|
-if 1:
|
|
- m1 = CurlMulti()
|
|
- m2 = CurlMulti()
|
|
- c = Curl()
|
|
- m1.add_handle(c)
|
|
- m1.remove_handle(c)
|
|
- m2.add_handle(c)
|
|
- del m1, m2, c
|
|
-
|
|
-
|
|
-# /***********************************************************************
|
|
-# // test copying and pickling - copying and pickling of
|
|
-# // instances of Curl and CurlMulti is not allowed
|
|
-# ************************************************************************/
|
|
-
|
|
-if 1 and copy:
|
|
- c = Curl()
|
|
- m = CurlMulti()
|
|
- try:
|
|
- copy.copy(c)
|
|
- except copy.Error:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error - copying should fail"
|
|
- try:
|
|
- copy.copy(m)
|
|
- except copy.Error:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error - copying should fail"
|
|
-
|
|
-if 1 and pickle:
|
|
- c = Curl()
|
|
- m = CurlMulti()
|
|
- fp = StringIO()
|
|
- p = pickle.Pickler(fp, 1)
|
|
- try:
|
|
- p.dump(c)
|
|
- except pickle.PicklingError:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error - pickling should fail"
|
|
- try:
|
|
- p.dump(m)
|
|
- except pickle.PicklingError:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error - pickling should fail"
|
|
- del c, m, fp, p
|
|
-
|
|
-if 1 and cPickle:
|
|
- c = Curl()
|
|
- m = CurlMulti()
|
|
- fp = StringIO()
|
|
- p = cPickle.Pickler(fp, 1)
|
|
- try:
|
|
- p.dump(c)
|
|
- except cPickle.PicklingError:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error - pickling should fail"
|
|
- try:
|
|
- p.dump(m)
|
|
- except cPickle.PicklingError:
|
|
- pass
|
|
- else:
|
|
- assert 0, "internal error - pickling should fail"
|
|
- del c, m, fp, p
|
|
-
|
|
-
|
|
-# /***********************************************************************
|
|
-# // test refcounts
|
|
-# ************************************************************************/
|
|
-
|
|
-# basic check of reference counting (use a memory checker like valgrind)
|
|
-if 1:
|
|
- c = Curl()
|
|
- m = CurlMulti()
|
|
- m.add_handle(c)
|
|
- del m
|
|
- m = CurlMulti()
|
|
- c.close()
|
|
- del m, c
|
|
-
|
|
-# basic check of cyclic garbage collection
|
|
-if 1 and gc:
|
|
- gc.collect()
|
|
- c = Curl()
|
|
- c.m = CurlMulti()
|
|
- c.m.add_handle(c)
|
|
- # create some nasty cyclic references
|
|
- c.c = c
|
|
- c.c.c1 = c
|
|
- c.c.c2 = c
|
|
- c.c.c3 = c.c
|
|
- c.c.c4 = c.m
|
|
- c.m.c = c
|
|
- c.m.m = c.m
|
|
- c.m.c = c
|
|
- # delete
|
|
- gc.collect()
|
|
- flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS
|
|
- if opts.verbose >= 1:
|
|
- flags = flags | gc.DEBUG_STATS
|
|
- gc.set_debug(flags)
|
|
- gc.collect()
|
|
- ##print gc.get_referrers(c)
|
|
- ##print gc.get_objects()
|
|
- if opts.verbose >= 1:
|
|
- 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())
|
|
-
|
|
-if 1:
|
|
- # Ensure that the refcounting error in "reset" is fixed:
|
|
- for i in xrange(100000):
|
|
- c = Curl()
|
|
- c.reset()
|
|
-
|
|
-# /***********************************************************************
|
|
-# // done
|
|
-# ************************************************************************/
|
|
-
|
|
-print "All tests passed."
|
|
diff --git a/tests/test_memleak.py b/tests/test_memleak.py
|
|
deleted file mode 100644
|
|
index 8577b97..0000000
|
|
--- a/tests/test_memleak.py
|
|
+++ /dev/null
|
|
@@ -1,53 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-#
|
|
-# just a simple self-test
|
|
-# need Python 2.2 or better for garbage collection
|
|
-#
|
|
-
|
|
-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 "PycURL version info", pycurl.version_info()
|
|
-print " %s, compiled %s" % (pycurl.__file__, pycurl.COMPILE_DATE)
|
|
-
|
|
-
|
|
-gc.collect()
|
|
-flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS
|
|
-if 1:
|
|
- flags = flags | gc.DEBUG_STATS
|
|
-gc.set_debug(flags)
|
|
-gc.collect()
|
|
-
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
-
|
|
-multi = pycurl.CurlMulti()
|
|
-t = []
|
|
-for a in range(100):
|
|
- curl = pycurl.Curl()
|
|
- multi.add_handle(curl)
|
|
- t.append(curl)
|
|
-
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
-
|
|
-for curl in t:
|
|
- curl.close()
|
|
- multi.remove_handle(curl)
|
|
-
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
-
|
|
-del curl
|
|
-del t
|
|
-del multi
|
|
-
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
-gc.collect()
|
|
-print "Tracked objects:", len(gc.get_objects())
|
|
-
|
|
-
|
|
diff --git a/tests/test_multi.py b/tests/test_multi.py
|
|
deleted file mode 100644
|
|
index 9193986..0000000
|
|
--- a/tests/test_multi.py
|
|
+++ /dev/null
|
|
@@ -1,33 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import pycurl
|
|
-
|
|
-m = pycurl.CurlMulti()
|
|
-m.handles = []
|
|
-c1 = pycurl.Curl()
|
|
-c2 = pycurl.Curl()
|
|
-c1.setopt(c1.URL, 'http://curl.haxx.se')
|
|
-c2.setopt(c2.URL, 'http://cnn.com')
|
|
-c2.setopt(c2.FOLLOWLOCATION, 1)
|
|
-m.add_handle(c1)
|
|
-m.add_handle(c2)
|
|
-m.handles.append(c1)
|
|
-m.handles.append(c2)
|
|
-
|
|
-num_handles = len(m.handles)
|
|
-while num_handles:
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
- m.select(1.0)
|
|
-
|
|
-m.remove_handle(c2)
|
|
-m.remove_handle(c1)
|
|
-del m.handles
|
|
-m.close()
|
|
-c1.close()
|
|
-c2.close()
|
|
diff --git a/tests/test_multi2.py b/tests/test_multi2.py
|
|
deleted file mode 100644
|
|
index 4b96789..0000000
|
|
--- a/tests/test_multi2.py
|
|
+++ /dev/null
|
|
@@ -1,72 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import os, sys
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-
|
|
-
|
|
-urls = (
|
|
- "http://curl.haxx.se",
|
|
- "http://www.python.org",
|
|
- "http://pycurl.sourceforge.net",
|
|
- "http://pycurl.sourceforge.net/tests/403_FORBIDDEN", # that actually exists ;-)
|
|
- "http://pycurl.sourceforge.net/tests/404_NOT_FOUND",
|
|
-)
|
|
-
|
|
-# Read list of URIs from file specified on commandline
|
|
-try:
|
|
- urls = open(sys.argv[1], "rb").readlines()
|
|
-except IndexError:
|
|
- # No file was specified
|
|
- pass
|
|
-
|
|
-# init
|
|
-m = pycurl.CurlMulti()
|
|
-m.handles = []
|
|
-for url in urls:
|
|
- c = pycurl.Curl()
|
|
- # save info in standard Python attributes
|
|
- c.url = url.rstrip()
|
|
- c.body = StringIO()
|
|
- c.http_code = -1
|
|
- m.handles.append(c)
|
|
- # pycurl API calls
|
|
- c.setopt(c.URL, c.url)
|
|
- c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
- m.add_handle(c)
|
|
-
|
|
-# get data
|
|
-num_handles = len(m.handles)
|
|
-while num_handles:
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
- # currently no more I/O is pending, could do something in the meantime
|
|
- # (display a progress bar, etc.)
|
|
- m.select(1.0)
|
|
-
|
|
-# close handles
|
|
-for c in m.handles:
|
|
- # save info in standard Python attributes
|
|
- c.http_code = c.getinfo(c.HTTP_CODE)
|
|
- # pycurl API calls
|
|
- m.remove_handle(c)
|
|
- c.close()
|
|
-m.close()
|
|
-
|
|
-# print result
|
|
-for c in m.handles:
|
|
- data = c.body.getvalue()
|
|
- if 0:
|
|
- print "**********", c.url, "**********"
|
|
- print data
|
|
- else:
|
|
- print "%-53s http_code %3d, %6d bytes" % (c.url, c.http_code, len(data))
|
|
-
|
|
diff --git a/tests/test_multi3.py b/tests/test_multi3.py
|
|
deleted file mode 100644
|
|
index 5b7ea6e..0000000
|
|
--- a/tests/test_multi3.py
|
|
+++ /dev/null
|
|
@@ -1,87 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-# same as test_multi2.py, but enforce some debugging and strange API-calls
|
|
-
|
|
-import os, sys
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-
|
|
-
|
|
-urls = (
|
|
- "http://curl.haxx.se",
|
|
- "http://www.python.org",
|
|
- "http://pycurl.sourceforge.net",
|
|
- "http://pycurl.sourceforge.net/THIS_HANDLE_IS_CLOSED",
|
|
-)
|
|
-
|
|
-# init
|
|
-m = pycurl.CurlMulti()
|
|
-m.handles = []
|
|
-for url in urls:
|
|
- c = pycurl.Curl()
|
|
- # save info in standard Python attributes
|
|
- c.url = url
|
|
- c.body = StringIO()
|
|
- c.http_code = -1
|
|
- c.debug = 0
|
|
- m.handles.append(c)
|
|
- # pycurl API calls
|
|
- c.setopt(c.URL, c.url)
|
|
- c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
- m.add_handle(c)
|
|
-
|
|
-# debug - close a handle
|
|
-if 1:
|
|
- c = m.handles[3]
|
|
- c.debug = 1
|
|
- c.close()
|
|
-
|
|
-# get data
|
|
-num_handles = len(m.handles)
|
|
-while num_handles:
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
- # currently no more I/O is pending, could do something in the meantime
|
|
- # (display a progress bar, etc.)
|
|
- m.select(1.0)
|
|
-
|
|
-# close handles
|
|
-for c in m.handles:
|
|
- # save info in standard Python attributes
|
|
- try:
|
|
- c.http_code = c.getinfo(c.HTTP_CODE)
|
|
- except pycurl.error:
|
|
- # handle already closed - see debug above
|
|
- assert c.debug
|
|
- c.http_code = -1
|
|
- # pycurl API calls
|
|
- if 0:
|
|
- m.remove_handle(c)
|
|
- c.close()
|
|
- elif 0:
|
|
- # in the C API this is the wrong calling order, but pycurl
|
|
- # handles this automatically
|
|
- c.close()
|
|
- m.remove_handle(c)
|
|
- else:
|
|
- # actually, remove_handle is called automatically on close
|
|
- c.close()
|
|
-m.close()
|
|
-
|
|
-# print result
|
|
-for c in m.handles:
|
|
- data = c.body.getvalue()
|
|
- if 0:
|
|
- print "**********", c.url, "**********"
|
|
- print data
|
|
- else:
|
|
- print "%-53s http_code %3d, %6d bytes" % (c.url, c.http_code, len(data))
|
|
-
|
|
diff --git a/tests/test_multi4.py b/tests/test_multi4.py
|
|
deleted file mode 100644
|
|
index f37ea26..0000000
|
|
--- a/tests/test_multi4.py
|
|
+++ /dev/null
|
|
@@ -1,57 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys, select, time
|
|
-import pycurl
|
|
-
|
|
-c1 = pycurl.Curl()
|
|
-c2 = pycurl.Curl()
|
|
-c3 = pycurl.Curl()
|
|
-c1.setopt(c1.URL, "http://www.python.org")
|
|
-c2.setopt(c2.URL, "http://curl.haxx.se")
|
|
-c3.setopt(c3.URL, "http://slashdot.org")
|
|
-c1.body = open("doc1", "wb")
|
|
-c2.body = open("doc2", "wb")
|
|
-c3.body = open("doc3", "wb")
|
|
-c1.setopt(c1.WRITEFUNCTION, c1.body.write)
|
|
-c2.setopt(c2.WRITEFUNCTION, c2.body.write)
|
|
-c3.setopt(c3.WRITEFUNCTION, c3.body.write)
|
|
-
|
|
-m = pycurl.CurlMulti()
|
|
-m.add_handle(c1)
|
|
-m.add_handle(c2)
|
|
-m.add_handle(c3)
|
|
-
|
|
-# Number of seconds to wait for a timeout to happen
|
|
-SELECT_TIMEOUT = 1.0
|
|
-
|
|
-# Stir the state machine into action
|
|
-while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
-# Keep going until all the connections have terminated
|
|
-while num_handles:
|
|
- apply(select.select, m.fdset() + (SELECT_TIMEOUT,))
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
-# Cleanup
|
|
-m.remove_handle(c3)
|
|
-m.remove_handle(c2)
|
|
-m.remove_handle(c1)
|
|
-m.close()
|
|
-c1.body.close()
|
|
-c2.body.close()
|
|
-c3.body.close()
|
|
-c1.close()
|
|
-c2.close()
|
|
-c3.close()
|
|
-print "http://www.python.org is in file doc1"
|
|
-print "http://curl.haxx.se is in file doc2"
|
|
-print "http://slashdot.org is in file doc3"
|
|
diff --git a/tests/test_multi5.py b/tests/test_multi5.py
|
|
deleted file mode 100644
|
|
index 3f0c8df..0000000
|
|
--- a/tests/test_multi5.py
|
|
+++ /dev/null
|
|
@@ -1,60 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys, select, time
|
|
-import pycurl
|
|
-
|
|
-c1 = pycurl.Curl()
|
|
-c2 = pycurl.Curl()
|
|
-c3 = pycurl.Curl()
|
|
-c1.setopt(c1.URL, "http://www.python.org")
|
|
-c2.setopt(c2.URL, "http://curl.haxx.se")
|
|
-c3.setopt(c3.URL, "http://slashdot.org")
|
|
-c1.body = open("doc1", "wb")
|
|
-c2.body = open("doc2", "wb")
|
|
-c3.body = open("doc3", "wb")
|
|
-c1.setopt(c1.WRITEFUNCTION, c1.body.write)
|
|
-c2.setopt(c2.WRITEFUNCTION, c2.body.write)
|
|
-c3.setopt(c3.WRITEFUNCTION, c3.body.write)
|
|
-
|
|
-m = pycurl.CurlMulti()
|
|
-m.add_handle(c1)
|
|
-m.add_handle(c2)
|
|
-m.add_handle(c3)
|
|
-
|
|
-# Number of seconds to wait for a timeout to happen
|
|
-SELECT_TIMEOUT = 1.0
|
|
-
|
|
-# Stir the state machine into action
|
|
-while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
-# Keep going until all the connections have terminated
|
|
-while num_handles:
|
|
- # The select method uses fdset internally to determine which file descriptors
|
|
- # to check.
|
|
- m.select(SELECT_TIMEOUT)
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
-# Cleanup
|
|
-m.remove_handle(c3)
|
|
-m.remove_handle(c2)
|
|
-m.remove_handle(c1)
|
|
-m.close()
|
|
-c1.body.close()
|
|
-c2.body.close()
|
|
-c3.body.close()
|
|
-c1.close()
|
|
-c2.close()
|
|
-c3.close()
|
|
-print "http://www.python.org is in file doc1"
|
|
-print "http://curl.haxx.se is in file doc2"
|
|
-print "http://slashdot.org is in file doc3"
|
|
-
|
|
diff --git a/tests/test_multi6.py b/tests/test_multi6.py
|
|
deleted file mode 100644
|
|
index 35a284f..0000000
|
|
--- a/tests/test_multi6.py
|
|
+++ /dev/null
|
|
@@ -1,62 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys, select, time
|
|
-import pycurl
|
|
-
|
|
-c1 = pycurl.Curl()
|
|
-c2 = pycurl.Curl()
|
|
-c3 = pycurl.Curl()
|
|
-c1.setopt(c1.URL, "http://www.python.org")
|
|
-c2.setopt(c2.URL, "http://curl.haxx.se")
|
|
-c3.setopt(c3.URL, "http://slashdot.org")
|
|
-c1.body = open("doc1", "wb")
|
|
-c2.body = open("doc2", "wb")
|
|
-c3.body = open("doc3", "wb")
|
|
-c1.setopt(c1.WRITEFUNCTION, c1.body.write)
|
|
-c2.setopt(c2.WRITEFUNCTION, c2.body.write)
|
|
-c3.setopt(c3.WRITEFUNCTION, c3.body.write)
|
|
-
|
|
-m = pycurl.CurlMulti()
|
|
-m.add_handle(c1)
|
|
-m.add_handle(c2)
|
|
-m.add_handle(c3)
|
|
-
|
|
-# Number of seconds to wait for a timeout to happen
|
|
-SELECT_TIMEOUT = 1.0
|
|
-
|
|
-# Stir the state machine into action
|
|
-while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
-# Keep going until all the connections have terminated
|
|
-while num_handles:
|
|
- # The select method uses fdset internally to determine which file descriptors
|
|
- # to check.
|
|
- m.select(SELECT_TIMEOUT)
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- # Print the message, if any
|
|
- print m.info_read(1)
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
-# Cleanup
|
|
-m.remove_handle(c3)
|
|
-m.remove_handle(c2)
|
|
-m.remove_handle(c1)
|
|
-m.close()
|
|
-c1.body.close()
|
|
-c2.body.close()
|
|
-c3.body.close()
|
|
-c1.close()
|
|
-c2.close()
|
|
-c3.close()
|
|
-print "http://www.python.org is in file doc1"
|
|
-print "http://curl.haxx.se is in file doc2"
|
|
-print "http://slashdot.org is in file doc3"
|
|
-
|
|
diff --git a/tests/test_multi_socket.py b/tests/test_multi_socket.py
|
|
deleted file mode 100644
|
|
index 6768061..0000000
|
|
--- a/tests/test_multi_socket.py
|
|
+++ /dev/null
|
|
@@ -1,82 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import os, sys
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-
|
|
-
|
|
-urls = (
|
|
- "http://curl.haxx.se",
|
|
- "http://www.python.org",
|
|
- "http://pycurl.sourceforge.net",
|
|
-)
|
|
-
|
|
-# Read list of URIs from file specified on commandline
|
|
-try:
|
|
- urls = open(sys.argv[1], "rb").readlines()
|
|
-except IndexError:
|
|
- # No file was specified
|
|
- pass
|
|
-
|
|
-# timer callback
|
|
-def timer(msecs):
|
|
- print 'Timer callback msecs:', msecs
|
|
-
|
|
-# socket callback
|
|
-def socket(event, socket, multi, data):
|
|
- print event, socket, multi, data
|
|
-# multi.assign(socket, timer)
|
|
-
|
|
-# init
|
|
-m = pycurl.CurlMulti()
|
|
-m.setopt(pycurl.M_PIPELINING, 1)
|
|
-m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
-m.setopt(pycurl.M_SOCKETFUNCTION, socket)
|
|
-m.handles = []
|
|
-for url in urls:
|
|
- c = pycurl.Curl()
|
|
- # save info in standard Python attributes
|
|
- c.url = url
|
|
- c.body = StringIO()
|
|
- c.http_code = -1
|
|
- m.handles.append(c)
|
|
- # pycurl API calls
|
|
- c.setopt(c.URL, c.url)
|
|
- c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
- m.add_handle(c)
|
|
-
|
|
-# get data
|
|
-num_handles = len(m.handles)
|
|
-while num_handles:
|
|
- while 1:
|
|
- ret, num_handles = m.socket_all()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
- # currently no more I/O is pending, could do something in the meantime
|
|
- # (display a progress bar, etc.)
|
|
- m.select(1.0)
|
|
-
|
|
-# close handles
|
|
-for c in m.handles:
|
|
- # save info in standard Python attributes
|
|
- c.http_code = c.getinfo(c.HTTP_CODE)
|
|
- # pycurl API calls
|
|
- m.remove_handle(c)
|
|
- c.close()
|
|
-m.close()
|
|
-
|
|
-# print result
|
|
-for c in m.handles:
|
|
- data = c.body.getvalue()
|
|
- if 0:
|
|
- print "**********", c.url, "**********"
|
|
- print data
|
|
- else:
|
|
- print "%-53s http_code %3d, %6d bytes" % (c.url, c.http_code, len(data))
|
|
-
|
|
diff --git a/tests/test_multi_socket_select.py b/tests/test_multi_socket_select.py
|
|
deleted file mode 100644
|
|
index 1f56d1d..0000000
|
|
--- a/tests/test_multi_socket_select.py
|
|
+++ /dev/null
|
|
@@ -1,105 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import os, sys
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-import select
|
|
-
|
|
-sockets = set()
|
|
-timeout = 0
|
|
-
|
|
-urls = (
|
|
- "http://curl.haxx.se",
|
|
- "http://www.python.org",
|
|
- "http://pycurl.sourceforge.net",
|
|
-)
|
|
-
|
|
-# Read list of URIs from file specified on commandline
|
|
-try:
|
|
- urls = open(sys.argv[1], "rb").readlines()
|
|
-except IndexError:
|
|
- # No file was specified
|
|
- pass
|
|
-
|
|
-# timer callback
|
|
-def timer(msecs):
|
|
- global timeout
|
|
- timeout = msecs
|
|
- print 'Timer callback msecs:', msecs
|
|
-
|
|
-# socket callback
|
|
-def socket(event, socket, multi, data):
|
|
- if event == pycurl.POLL_REMOVE:
|
|
- print "Remove Socket %d"%socket
|
|
- sockets.remove(socket)
|
|
- else:
|
|
- if socket not in sockets:
|
|
- print "Add socket %d"%socket
|
|
- sockets.add(socket)
|
|
- print event, socket, multi, data
|
|
-
|
|
-# init
|
|
-m = pycurl.CurlMulti()
|
|
-m.setopt(pycurl.M_PIPELINING, 1)
|
|
-m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
-m.setopt(pycurl.M_SOCKETFUNCTION, socket)
|
|
-m.handles = []
|
|
-for url in urls:
|
|
- c = pycurl.Curl()
|
|
- # save info in standard Python attributes
|
|
- c.url = url
|
|
- c.body = StringIO()
|
|
- c.http_code = -1
|
|
- m.handles.append(c)
|
|
- # pycurl API calls
|
|
- c.setopt(c.URL, c.url)
|
|
- c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
- m.add_handle(c)
|
|
-
|
|
-# get data
|
|
-num_handles = len(m.handles)
|
|
-
|
|
-while (pycurl.E_CALL_MULTI_PERFORM==m.socket_all()[0]):
|
|
- pass
|
|
-
|
|
-timeout = m.timeout()
|
|
-
|
|
-
|
|
-while True:
|
|
- (rr, wr, er) = select.select(sockets,sockets,sockets,timeout/1000.0)
|
|
- socketSet = set(rr+wr+er)
|
|
- if socketSet:
|
|
- for s in socketSet:
|
|
- while True:
|
|
- (ret,running) = m.socket_action(s,0)
|
|
- if ret!=pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
- else:
|
|
- (ret,running) = m.socket_action(pycurl.SOCKET_TIMEOUT,0)
|
|
- if running==0:
|
|
- break
|
|
-
|
|
-# close handles
|
|
-for c in m.handles:
|
|
- # save info in standard Python attributes
|
|
- c.http_code = c.getinfo(c.HTTP_CODE)
|
|
- # pycurl API calls
|
|
- m.remove_handle(c)
|
|
- c.close()
|
|
-m.close()
|
|
-
|
|
-# print result
|
|
-for c in m.handles:
|
|
- data = c.body.getvalue()
|
|
- if 0:
|
|
- print "**********", c.url, "**********"
|
|
- print data
|
|
- else:
|
|
- print "%-53s http_code %3d, %6d bytes" % (c.url, c.http_code, len(data))
|
|
-
|
|
diff --git a/tests/test_multi_timer.py b/tests/test_multi_timer.py
|
|
deleted file mode 100644
|
|
index 17371d3..0000000
|
|
--- a/tests/test_multi_timer.py
|
|
+++ /dev/null
|
|
@@ -1,76 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import os, sys
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-
|
|
-
|
|
-urls = (
|
|
- "http://curl.haxx.se",
|
|
- "http://www.python.org",
|
|
- "http://pycurl.sourceforge.net",
|
|
-)
|
|
-
|
|
-# Read list of URIs from file specified on commandline
|
|
-try:
|
|
- urls = open(sys.argv[1], "rb").readlines()
|
|
-except IndexError:
|
|
- # No file was specified
|
|
- pass
|
|
-
|
|
-# timer callback
|
|
-def timer(msecs):
|
|
- print 'Timer callback msecs:', msecs
|
|
-
|
|
-# init
|
|
-m = pycurl.CurlMulti()
|
|
-m.setopt(pycurl.M_PIPELINING, 1)
|
|
-m.setopt(pycurl.M_TIMERFUNCTION, timer)
|
|
-m.handles = []
|
|
-for url in urls:
|
|
- c = pycurl.Curl()
|
|
- # save info in standard Python attributes
|
|
- c.url = url
|
|
- c.body = StringIO()
|
|
- c.http_code = -1
|
|
- m.handles.append(c)
|
|
- # pycurl API calls
|
|
- c.setopt(c.URL, c.url)
|
|
- c.setopt(c.WRITEFUNCTION, c.body.write)
|
|
- m.add_handle(c)
|
|
-
|
|
-# get data
|
|
-num_handles = len(m.handles)
|
|
-while num_handles:
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
- # currently no more I/O is pending, could do something in the meantime
|
|
- # (display a progress bar, etc.)
|
|
- m.select(1.0)
|
|
-
|
|
-# close handles
|
|
-for c in m.handles:
|
|
- # save info in standard Python attributes
|
|
- c.http_code = c.getinfo(c.HTTP_CODE)
|
|
- # pycurl API calls
|
|
- m.remove_handle(c)
|
|
- c.close()
|
|
-m.close()
|
|
-
|
|
-# print result
|
|
-for c in m.handles:
|
|
- data = c.body.getvalue()
|
|
- if 0:
|
|
- print "**********", c.url, "**********"
|
|
- print data
|
|
- else:
|
|
- print "%-53s http_code %3d, %6d bytes" % (c.url, c.http_code, len(data))
|
|
-
|
|
diff --git a/tests/test_multi_vs_thread.py b/tests/test_multi_vs_thread.py
|
|
deleted file mode 100644
|
|
index 0caed60..0000000
|
|
--- a/tests/test_multi_vs_thread.py
|
|
+++ /dev/null
|
|
@@ -1,262 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import os, sys, time
|
|
-from threading import Thread, RLock
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-
|
|
-# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
|
|
-# the libcurl tutorial for more info.
|
|
-try:
|
|
- import signal
|
|
- from signal import SIGPIPE, SIG_IGN
|
|
- signal.signal(signal.SIGPIPE, signal.SIG_IGN)
|
|
-except ImportError:
|
|
- pass
|
|
-
|
|
-# The conclusion is: the multi interface is fastest!
|
|
-
|
|
-NUM_PAGES = 30
|
|
-NUM_THREADS = 10
|
|
-assert NUM_PAGES % NUM_THREADS == 0
|
|
-
|
|
-##URL = "http://pycurl.sourceforge.net/tests/testgetvars.php?%d"
|
|
-URL = "http://pycurl.sourceforge.net/tests/teststaticpage.html?%d"
|
|
-
|
|
-
|
|
-#
|
|
-# util
|
|
-#
|
|
-
|
|
-class Curl:
|
|
- def __init__(self, url):
|
|
- self.url = url
|
|
- self.body = StringIO()
|
|
- self.http_code = -1
|
|
- # pycurl API calls
|
|
- self._curl = pycurl.Curl()
|
|
- self._curl.setopt(pycurl.URL, self.url)
|
|
- self._curl.setopt(pycurl.WRITEFUNCTION, self.body.write)
|
|
- self._curl.setopt(pycurl.NOSIGNAL, 1)
|
|
-
|
|
- def perform(self):
|
|
- self._curl.perform()
|
|
-
|
|
- def close(self):
|
|
- self.http_code = self._curl.getinfo(pycurl.HTTP_CODE)
|
|
- self._curl.close()
|
|
-
|
|
-
|
|
-def print_result(items):
|
|
- return # DO NOTHING
|
|
- #
|
|
- for c in items:
|
|
- data = c.body.getvalue()
|
|
- if 0:
|
|
- print "**********", c.url, "**********"
|
|
- print data
|
|
- elif 1:
|
|
- print "%-60s %3d %6d" % (c.url, c.http_code, len(data))
|
|
-
|
|
-
|
|
-###
|
|
-### 1) multi
|
|
-###
|
|
-
|
|
-def test_multi():
|
|
- clock1 = time.time()
|
|
-
|
|
- # init
|
|
- handles = []
|
|
- m = pycurl.CurlMulti()
|
|
- for i in range(NUM_PAGES):
|
|
- c = Curl(URL %i)
|
|
- m.add_handle(c._curl)
|
|
- handles.append(c)
|
|
-
|
|
- clock2 = time.time()
|
|
-
|
|
- # stir state machine into action
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
- # get data
|
|
- while num_handles:
|
|
- m.select(1.0)
|
|
- while 1:
|
|
- ret, num_handles = m.perform()
|
|
- if ret != pycurl.E_CALL_MULTI_PERFORM:
|
|
- break
|
|
-
|
|
- clock3 = time.time()
|
|
-
|
|
- # close handles
|
|
- for c in handles:
|
|
- c.close()
|
|
- m.close()
|
|
-
|
|
- clock4 = time.time()
|
|
- print "multi interface: %d pages: perform %5.2f secs, total %5.2f secs" % (NUM_PAGES, clock3 - clock2, clock4 - clock1)
|
|
-
|
|
- # print result
|
|
- print_result(handles)
|
|
-
|
|
-
|
|
-
|
|
-###
|
|
-### 2) thread
|
|
-###
|
|
-
|
|
-class Test(Thread):
|
|
- def __init__(self, lock=None):
|
|
- Thread.__init__(self)
|
|
- self.lock = lock
|
|
- self.items = []
|
|
-
|
|
- def run(self):
|
|
- if self.lock:
|
|
- self.lock.acquire()
|
|
- self.lock.release()
|
|
- for c in self.items:
|
|
- c.perform()
|
|
-
|
|
-
|
|
-def test_threads(lock=None):
|
|
- clock1 = time.time()
|
|
-
|
|
- # create and start threads, but block them
|
|
- if lock:
|
|
- lock.acquire()
|
|
-
|
|
- # init (FIXME - this is ugly)
|
|
- threads = []
|
|
- handles = []
|
|
- t = None
|
|
- for i in range(NUM_PAGES):
|
|
- if i % (NUM_PAGES / NUM_THREADS) == 0:
|
|
- t = Test(lock)
|
|
- if lock:
|
|
- t.start()
|
|
- threads.append(t)
|
|
- c = Curl(URL % i)
|
|
- t.items.append(c)
|
|
- handles.append(c)
|
|
- assert len(handles) == NUM_PAGES
|
|
- assert len(threads) == NUM_THREADS
|
|
-
|
|
- clock2 = time.time()
|
|
-
|
|
- #
|
|
- if lock:
|
|
- # release lock to let the blocked threads run
|
|
- lock.release()
|
|
- else:
|
|
- # start threads
|
|
- for t in threads:
|
|
- t.start()
|
|
- # wait for threads to finish
|
|
- for t in threads:
|
|
- t.join()
|
|
-
|
|
- clock3 = time.time()
|
|
-
|
|
- # close handles
|
|
- for c in handles:
|
|
- c.close()
|
|
-
|
|
- clock4 = time.time()
|
|
- if lock:
|
|
- print "thread interface [lock]: %d pages: perform %5.2f secs, total %5.2f secs" % (NUM_PAGES, clock3 - clock2, clock4 - clock1)
|
|
- else:
|
|
- print "thread interface: %d pages: perform %5.2f secs, total %5.2f secs" % (NUM_PAGES, clock3 - clock2, clock4 - clock1)
|
|
-
|
|
- # print result
|
|
- print_result(handles)
|
|
-
|
|
-
|
|
-
|
|
-###
|
|
-### 3) thread - threads grab curl objects on demand from a shared pool
|
|
-###
|
|
-
|
|
-class TestPool(Thread):
|
|
- def __init__(self, lock, pool):
|
|
- Thread.__init__(self)
|
|
- self.lock = lock
|
|
- self.pool = pool
|
|
-
|
|
- def run(self):
|
|
- while 1:
|
|
- self.lock.acquire()
|
|
- c = None
|
|
- if self.pool:
|
|
- c = self.pool.pop()
|
|
- self.lock.release()
|
|
- if c is None:
|
|
- break
|
|
- c.perform()
|
|
-
|
|
-
|
|
-def test_thread_pool(lock):
|
|
- clock1 = time.time()
|
|
-
|
|
- # init
|
|
- handles = []
|
|
- for i in range(NUM_PAGES):
|
|
- c = Curl(URL %i)
|
|
- handles.append(c)
|
|
-
|
|
- # create and start threads, but block them
|
|
- lock.acquire()
|
|
- threads = []
|
|
- pool = handles[:] # shallow copy of the list, shared for pop()
|
|
- for i in range(NUM_THREADS):
|
|
- t = TestPool(lock, pool)
|
|
- t.start()
|
|
- threads.append(t)
|
|
- assert len(pool) == NUM_PAGES
|
|
- assert len(threads) == NUM_THREADS
|
|
-
|
|
- clock2 = time.time()
|
|
-
|
|
- # release lock to let the blocked threads run
|
|
- lock.release()
|
|
-
|
|
- # wait for threads to finish
|
|
- for t in threads:
|
|
- t.join()
|
|
-
|
|
- clock3 = time.time()
|
|
-
|
|
- # close handles
|
|
- for c in handles:
|
|
- c.close()
|
|
-
|
|
- clock4 = time.time()
|
|
- print "thread interface [pool]: %d pages: perform %5.2f secs, total %5.2f secs" % (NUM_PAGES, clock3 - clock2, clock4 - clock1)
|
|
-
|
|
- # print result
|
|
- print_result(handles)
|
|
-
|
|
-
|
|
-
|
|
-lock = RLock()
|
|
-if 1:
|
|
- test_multi()
|
|
- test_threads()
|
|
- test_threads(lock)
|
|
- test_thread_pool(lock)
|
|
-else:
|
|
- test_thread_pool(lock)
|
|
- test_threads(lock)
|
|
- test_threads()
|
|
- test_multi()
|
|
-
|
|
diff --git a/tests/test_post.py b/tests/test_post.py
|
|
deleted file mode 100644
|
|
index f0a8ad0..0000000
|
|
--- a/tests/test_post.py
|
|
+++ /dev/null
|
|
@@ -1,24 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import urllib
|
|
-import pycurl
|
|
-
|
|
-# simple
|
|
-pf = {'field1': 'value1'}
|
|
-
|
|
-# multiple fields
|
|
-pf = {'field1':'value1', 'field2':'value2 with blanks', 'field3':'value3'}
|
|
-
|
|
-# multiple fields with & in field
|
|
-pf = {'field1':'value1', 'field2':'value2 with blanks and & chars',
|
|
- 'field3':'value3'}
|
|
-
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, 'http://pycurl.sourceforge.net/tests/testpostvars.php')
|
|
-c.setopt(c.POSTFIELDS, urllib.urlencode(pf))
|
|
-c.setopt(c.VERBOSE, 1)
|
|
-c.perform()
|
|
-c.close()
|
|
diff --git a/tests/test_post2.py b/tests/test_post2.py
|
|
deleted file mode 100644
|
|
index 74a6eca..0000000
|
|
--- a/tests/test_post2.py
|
|
+++ /dev/null
|
|
@@ -1,18 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import pycurl
|
|
-
|
|
-pf = [('field1', 'this is a test using httppost & stuff'),
|
|
- ('field2', (pycurl.FORM_FILE, 'test_post.py', pycurl.FORM_FILE, 'test_post2.py')),
|
|
- ('field3', (pycurl.FORM_CONTENTS, 'this is wei\000rd, but null-bytes are okay'))
|
|
- ]
|
|
-
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, 'http://www.contactor.se/~dast/postit.cgi')
|
|
-c.setopt(c.HTTPPOST, pf)
|
|
-c.setopt(c.VERBOSE, 1)
|
|
-c.perform()
|
|
-c.close()
|
|
diff --git a/tests/test_post3.py b/tests/test_post3.py
|
|
deleted file mode 100644
|
|
index 617eba2..0000000
|
|
--- a/tests/test_post3.py
|
|
+++ /dev/null
|
|
@@ -1,32 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import urllib
|
|
-POSTSTRING = urllib.urlencode({'field1':'value1', 'field2':'value2 with blanks', 'field3':'value3'})
|
|
-
|
|
-class test:
|
|
-
|
|
- def __init__(self):
|
|
- self.finished = False
|
|
-
|
|
- def read_cb(self, size):
|
|
- assert len(POSTSTRING) <= size
|
|
- if not self.finished:
|
|
- self.finished = True
|
|
- return POSTSTRING
|
|
- else:
|
|
- # Nothing more to read
|
|
- return ""
|
|
-
|
|
-import pycurl
|
|
-c = pycurl.Curl()
|
|
-t = test()
|
|
-c.setopt(c.URL, 'http://pycurl.sourceforge.net/tests/testpostvars.php')
|
|
-c.setopt(c.POST, 1)
|
|
-c.setopt(c.POSTFIELDSIZE, len(POSTSTRING))
|
|
-c.setopt(c.READFUNCTION, t.read_cb)
|
|
-c.setopt(c.VERBOSE, 1)
|
|
-c.perform()
|
|
-c.close()
|
|
diff --git a/tests/test_reset.py b/tests/test_reset.py
|
|
deleted file mode 100644
|
|
index 1addcfe..0000000
|
|
--- a/tests/test_reset.py
|
|
+++ /dev/null
|
|
@@ -1,75 +0,0 @@
|
|
-#!/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()
|
|
-
|
|
diff --git a/tests/test_share.py b/tests/test_share.py
|
|
deleted file mode 100644
|
|
index 3332cda..0000000
|
|
--- a/tests/test_share.py
|
|
+++ /dev/null
|
|
@@ -1,34 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys
|
|
-import pycurl
|
|
-import threading
|
|
-
|
|
-print >>sys.stderr, 'Testing', pycurl.version
|
|
-
|
|
-
|
|
-class Test(threading.Thread):
|
|
-
|
|
- def __init__(self, share):
|
|
- threading.Thread.__init__(self)
|
|
- self.curl = pycurl.Curl()
|
|
- self.curl.setopt(pycurl.URL, 'http://curl.haxx.se')
|
|
- self.curl.setopt(pycurl.SHARE, share)
|
|
-
|
|
- def run(self):
|
|
- self.curl.perform()
|
|
- self.curl.close()
|
|
-
|
|
-s = pycurl.CurlShare()
|
|
-s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_COOKIE)
|
|
-s.setopt(pycurl.SH_SHARE, pycurl.LOCK_DATA_DNS)
|
|
-
|
|
-t1 = Test(s)
|
|
-t2 = Test(s)
|
|
-
|
|
-t1.start()
|
|
-t2.start()
|
|
-del s
|
|
diff --git a/tests/test_socketopen.py b/tests/test_socketopen.py
|
|
deleted file mode 100644
|
|
index d3f0a62..0000000
|
|
--- a/tests/test_socketopen.py
|
|
+++ /dev/null
|
|
@@ -1,17 +0,0 @@
|
|
-import pycurl
|
|
-import StringIO
|
|
-import socket
|
|
-
|
|
-def socketopen(family, socktype, protocol):
|
|
- print family, socktype, protocol
|
|
- s = socket.socket(family, socktype, protocol)
|
|
- s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
- return s
|
|
-
|
|
-sio = StringIO.StringIO()
|
|
-
|
|
-c = pycurl.Curl()
|
|
-c.setopt(pycurl.OPENSOCKETFUNCTION, socketopen)
|
|
-c.setopt(pycurl.URL, 'http://camvine.com')
|
|
-c.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
-c.perform()
|
|
diff --git a/tests/test_stringio.py b/tests/test_stringio.py
|
|
deleted file mode 100644
|
|
index 25e639b..0000000
|
|
--- a/tests/test_stringio.py
|
|
+++ /dev/null
|
|
@@ -1,25 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-# $Id$
|
|
-
|
|
-import sys
|
|
-try:
|
|
- from cStringIO import StringIO
|
|
-except ImportError:
|
|
- from StringIO import StringIO
|
|
-import pycurl
|
|
-
|
|
-url = "http://curl.haxx.se/dev/"
|
|
-
|
|
-print "Testing", pycurl.version
|
|
-
|
|
-body = StringIO()
|
|
-c = pycurl.Curl()
|
|
-c.setopt(c.URL, url)
|
|
-c.setopt(c.WRITEFUNCTION, body.write)
|
|
-c.perform()
|
|
-c.close()
|
|
-
|
|
-contents = body.getvalue()
|
|
-print contents
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From f19bc32a8351b67ab3690b3ee0d4fe6843749a9b Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 13:36:38 -0500
|
|
Subject: [PATCH 063/149] Fix make test to run nosetests (closes #5)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
Makefile | 4 +++-
|
|
1 files changed, 3 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 9b2369d..9475250 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -7,6 +7,7 @@ SHELL = /bin/sh
|
|
|
|
PYTHON = python2.3
|
|
PYTHON = python
|
|
+NOSETESTS = nosetests
|
|
|
|
all build:
|
|
$(PYTHON) setup.py build
|
|
@@ -15,7 +16,8 @@ build-7.10.8:
|
|
$(PYTHON) setup.py build --curl-config=/home/hosts/localhost/packages/curl-7.10.8/bin/curl-config
|
|
|
|
test: build
|
|
- $(PYTHON) tests/test_internals.py -q
|
|
+ PYTHONPATH=$$(ls -d build/lib.*):$$PYTHONPATH \
|
|
+ $(NOSETESTS)
|
|
|
|
# (needs GNU binutils)
|
|
strip: build
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 61d61649b7687c85bdcef3da3650bcce03c4735d Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:25:47 -0500
|
|
Subject: [PATCH 064/149] First stab at travis configuration
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.travis.yml | 11 +++++++++++
|
|
requirements-dev.txt | 1 +
|
|
2 files changed, 12 insertions(+), 0 deletions(-)
|
|
create mode 100644 .travis.yml
|
|
create mode 100644 requirements-dev.txt
|
|
|
|
diff --git a/.travis.yml b/.travis.yml
|
|
new file mode 100644
|
|
index 0000000..2350dfb
|
|
--- /dev/null
|
|
+++ b/.travis.yml
|
|
@@ -0,0 +1,11 @@
|
|
+language: python
|
|
+python:
|
|
+ - "2.5"
|
|
+ - "2.6"
|
|
+ - "2.7"
|
|
+install: >
|
|
+ pip install -r requirements-dev.txt --use-mirrors &&
|
|
+ sudo apt-get install vsftpd
|
|
+script: >
|
|
+ export PYCURL_VSFTPD_PATH=/usr/sbin/vsftpd &&
|
|
+ nosetests
|
|
diff --git a/requirements-dev.txt b/requirements-dev.txt
|
|
new file mode 100644
|
|
index 0000000..f3c7e8e
|
|
--- /dev/null
|
|
+++ b/requirements-dev.txt
|
|
@@ -0,0 +1 @@
|
|
+nose
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 8ceafd381dd7bca305686e33529a207b6544e2b4 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:37:47 -0500
|
|
Subject: [PATCH 065/149] Building the C module will help
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.travis.yml | 2 ++
|
|
1 files changed, 2 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/.travis.yml b/.travis.yml
|
|
index 2350dfb..ae17929 100644
|
|
--- a/.travis.yml
|
|
+++ b/.travis.yml
|
|
@@ -7,5 +7,7 @@ install: >
|
|
pip install -r requirements-dev.txt --use-mirrors &&
|
|
sudo apt-get install vsftpd
|
|
script: >
|
|
+ make &&
|
|
+ export PYTHONPATH=build/lib.* &&
|
|
export PYCURL_VSFTPD_PATH=/usr/sbin/vsftpd &&
|
|
nosetests
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 1365d5ca2d70074d588cd23392862264494f0eeb Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:45:46 -0500
|
|
Subject: [PATCH 066/149] Go through more hoops (/bin/dash in play?)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.travis.yml | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/.travis.yml b/.travis.yml
|
|
index ae17929..4afdff9 100644
|
|
--- a/.travis.yml
|
|
+++ b/.travis.yml
|
|
@@ -8,6 +8,6 @@ install: >
|
|
sudo apt-get install vsftpd
|
|
script: >
|
|
make &&
|
|
- export PYTHONPATH=build/lib.* &&
|
|
+ export PYTHONPATH=$(ls -d build/lib.*) &&
|
|
export PYCURL_VSFTPD_PATH=/usr/sbin/vsftpd &&
|
|
nosetests
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 99896926cfdfc180f8c330cf2371c6cb023b4bac Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:50:21 -0500
|
|
Subject: [PATCH 067/149] Forgot about bottle
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
requirements-dev.txt | 1 +
|
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/requirements-dev.txt b/requirements-dev.txt
|
|
index f3c7e8e..36b0b24 100644
|
|
--- a/requirements-dev.txt
|
|
+++ b/requirements-dev.txt
|
|
@@ -1 +1,2 @@
|
|
+bottle
|
|
nose
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From ce37bf646c42352895ba83c6bf7364012666c5c7 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:20:25 -0500
|
|
Subject: [PATCH 068/149] Python 2.5 needs simplejson
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.travis.yml | 6 +++++-
|
|
requirements-dev-2.5.txt | 2 ++
|
|
2 files changed, 7 insertions(+), 1 deletions(-)
|
|
create mode 100644 requirements-dev-2.5.txt
|
|
|
|
diff --git a/.travis.yml b/.travis.yml
|
|
index 4afdff9..4268895 100644
|
|
--- a/.travis.yml
|
|
+++ b/.travis.yml
|
|
@@ -4,7 +4,11 @@ python:
|
|
- "2.6"
|
|
- "2.7"
|
|
install: >
|
|
- pip install -r requirements-dev.txt --use-mirrors &&
|
|
+ if test -e requirements-dev-$TRAVIS_PYTHON_VERSION.txt; then
|
|
+ pip install -r requirements-dev-$TRAVIS_PYTHON_VERSION.txt --use-mirrors
|
|
+ else
|
|
+ pip install -r requirements-dev.txt --use-mirrors
|
|
+ fi &&
|
|
sudo apt-get install vsftpd
|
|
script: >
|
|
make &&
|
|
diff --git a/requirements-dev-2.5.txt b/requirements-dev-2.5.txt
|
|
new file mode 100644
|
|
index 0000000..52e3460
|
|
--- /dev/null
|
|
+++ b/requirements-dev-2.5.txt
|
|
@@ -0,0 +1,2 @@
|
|
+-r requirements-dev.txt
|
|
+simplejson
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bc7eb4aad84f8249356c9d221fd5f404943f6699 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 7 Mar 2013 04:23:52 -0500
|
|
Subject: [PATCH 069/149] Expand readme (mostly borrowed from @Lispython's fork)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
README | 13 --------
|
|
README.rst | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 93 insertions(+), 13 deletions(-)
|
|
delete mode 100644 README
|
|
create mode 100644 README.rst
|
|
|
|
diff --git a/README b/README
|
|
deleted file mode 100644
|
|
index 6b3e1d4..0000000
|
|
--- a/README
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-License
|
|
--------
|
|
-
|
|
-Copyright (C) 2001-2008 by Kjetil Jacobsen <kjetilja at gmail.com>
|
|
-Copyright (C) 2001-2008 by Markus F.X.J. Oberhumer <markus at oberhumer.com>
|
|
-
|
|
-All rights reserved.
|
|
-
|
|
-PycURL is dual licensed under the LGPL and an MIT/X derivative license
|
|
-based on the cURL license. A full copy of the LGPL license is included
|
|
-in the file COPYING. A full copy of the MIT/X derivative license is
|
|
-included in the file COPYING2. You can redistribute and/or modify PycURL
|
|
-according to the terms of either license.
|
|
diff --git a/README.rst b/README.rst
|
|
new file mode 100644
|
|
index 0000000..3518d9d
|
|
--- /dev/null
|
|
+++ b/README.rst
|
|
@@ -0,0 +1,93 @@
|
|
+PycURL: Python interface to libcurl
|
|
+====================================
|
|
+
|
|
+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 `urllib`_ Python module.
|
|
+PycURL is mature, very fast, and supports a lot of features.
|
|
+
|
|
+Overview
|
|
+--------
|
|
+
|
|
+- libcurl is a free and easy-to-use client-side URL transfer library, supporting
|
|
+ FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, IMAP,
|
|
+ SMTP, POP3 and RTSP. libcurl supports SSL certificates, HTTP POST, HTTP PUT,
|
|
+ FTP uploading, HTTP form based upload, proxies, cookies, user+password
|
|
+ authentication (Basic, Digest, NTLM, Negotiate, Kerberos4), file transfer
|
|
+ resume, http proxy tunneling and more!
|
|
+
|
|
+- libcurl is highly portable, it builds and works identically on numerous
|
|
+ platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX,
|
|
+ AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X,
|
|
+ Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS and more...
|
|
+
|
|
+- libcurl is `free`_, `thread-safe`_, `IPv6 compatible`_, `feature rich`_,
|
|
+ `well supported`_, `fast`_, `thoroughly documented`_ and is already used by
|
|
+ many known, big and successful `companies`_ and numerous `applications`_.
|
|
+
|
|
+.. _free: http://curl.haxx.se/docs/copyright.html
|
|
+.. _thread-safe: http://curl.haxx.se/libcurl/features.html#thread
|
|
+.. _`IPv6 compatible`: http://curl.haxx.se/libcurl/features.html#ipv6
|
|
+.. _`feature rich`: http://curl.haxx.se/libcurl/features.html#features
|
|
+.. _`well supported`: http://curl.haxx.se/libcurl/features.html#support
|
|
+.. _`fast`: http://curl.haxx.se/libcurl/features.html#fast
|
|
+.. _`thoroughly documented`: http://curl.haxx.se/libcurl/features.html#docs
|
|
+.. _companies: http://curl.haxx.se/docs/companies.html
|
|
+.. _applications: http://curl.haxx.se/libcurl/using/apps.html
|
|
+
|
|
+Installation
|
|
+------------
|
|
+
|
|
+You can install the most recent PycURL version using `easy_install`_::
|
|
+
|
|
+ easy_install pycurl
|
|
+
|
|
+or `pip`_::
|
|
+
|
|
+ pip install pycurl
|
|
+
|
|
+
|
|
+.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
|
|
+.. _pip: http://pypi.python.org/pypi/pip
|
|
+
|
|
+Contribute
|
|
+----------
|
|
+
|
|
+For smaller changes:
|
|
+
|
|
+#. Fork `the repository`_ on Github.
|
|
+#. Create a branch off **master**.
|
|
+#. Make your changes.
|
|
+#. Write a test which shows that the bug was fixed or that the feature
|
|
+ works as expected.
|
|
+#. Send a pull request.
|
|
+
|
|
+For larger changes:
|
|
+
|
|
+#. Join the `mailing list`_.
|
|
+#. Discuss your proposal on the mailing list.
|
|
+#. When consensus is reached, implement it as described above.
|
|
+
|
|
+.. image:: https://api.travis-ci.org/p/pycurl.png
|
|
+ :target: https://travis-ci.org/p/pycurl
|
|
+
|
|
+License
|
|
+-------
|
|
+
|
|
+::
|
|
+
|
|
+ Copyright (C) 2001-2008 by Kjetil Jacobsen <kjetilja at gmail.com>
|
|
+ Copyright (C) 2001-2008 by Markus F.X.J. Oberhumer <markus at oberhumer.com>
|
|
+
|
|
+ All rights reserved.
|
|
+
|
|
+ PycURL is dual licensed under the LGPL and an MIT/X derivative license
|
|
+ based on the cURL license. A full copy of the LGPL license is included
|
|
+ in the file COPYING. A full copy of the MIT/X derivative license is
|
|
+ included in the file COPYING2. You can redistribute and/or modify PycURL
|
|
+ according to the terms of either license.
|
|
+
|
|
+.. _PycURL: http://pycurl.sourceforge.net/
|
|
+.. _libcurl: http://curl.haxx.se/libcurl/
|
|
+.. _urllib: http://docs.python.org/library/urllib.html
|
|
+.. _`the repository`: https://github.com/p/pycurl
|
|
+.. _`mailing list`: http://cool.haxx.se/mailman/listinfo/curl-and-python
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 0d6217a0204fe48fae9b6db0b5b73f2a71cdb90c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 7 Mar 2013 04:30:23 -0500
|
|
Subject: [PATCH 070/149] Readme -> readme.rst elsewhere
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
MANIFEST.in | 2 +-
|
|
setup.py | 2 +-
|
|
tests/ftp_test.py | 6 +++---
|
|
tests/post_test.py | 4 ++--
|
|
4 files changed, 7 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/MANIFEST.in b/MANIFEST.in
|
|
index 7d5aaf5..11ce1fe 100644
|
|
--- a/MANIFEST.in
|
|
+++ b/MANIFEST.in
|
|
@@ -8,7 +8,7 @@ include COPYING
|
|
include COPYING2
|
|
include INSTALL
|
|
include Makefile
|
|
-include README
|
|
+include README.rst
|
|
include TODO
|
|
include MANIFEST.in
|
|
include src/Makefile
|
|
diff --git a/setup.py b/setup.py
|
|
index 33704ef..235e4c9 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -166,7 +166,7 @@ def get_data_files():
|
|
else:
|
|
datadir = os.path.join("share", "doc", PACKAGE)
|
|
#
|
|
- files = ["ChangeLog", "COPYING", "COPYING2", "INSTALL", "README", "TODO",]
|
|
+ files = ["ChangeLog", "COPYING", "COPYING2", "INSTALL", "README.rst", "TODO",]
|
|
if files:
|
|
data_files.append((os.path.join(datadir), files))
|
|
files = glob.glob(os.path.join("doc", "*.html"))
|
|
diff --git a/tests/ftp_test.py b/tests/ftp_test.py
|
|
index fa2ef79..5ee380c 100644
|
|
--- a/tests/ftp_test.py
|
|
+++ b/tests/ftp_test.py
|
|
@@ -26,7 +26,7 @@ class FtpTest(unittest.TestCase):
|
|
self.curl.perform()
|
|
|
|
result = sio.getvalue()
|
|
- assert 'README' in result
|
|
+ assert 'README.rst' in result
|
|
assert 'INSTALL' in result
|
|
|
|
# XXX this test needs to be fixed
|
|
@@ -38,7 +38,7 @@ class FtpTest(unittest.TestCase):
|
|
self.curl.perform()
|
|
|
|
result = sio.getvalue()
|
|
- assert 'README' not in result
|
|
+ assert 'README.rst' not in result
|
|
assert 'ftp_test.py' in result
|
|
|
|
def test_epsv(self):
|
|
@@ -49,5 +49,5 @@ class FtpTest(unittest.TestCase):
|
|
self.curl.perform()
|
|
|
|
result = sio.getvalue()
|
|
- assert 'README' in result
|
|
+ assert 'README.rst' in result
|
|
assert 'INSTALL' in result
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index e8b0675..6f9d8d4 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -81,7 +81,7 @@ class PostTest(unittest.TestCase):
|
|
self.check_post(send, expect, 'http://localhost:8380/postfields')
|
|
|
|
def test_post_file(self):
|
|
- path = os.path.join(os.path.dirname(__file__), '..', 'README')
|
|
+ path = os.path.join(os.path.dirname(__file__), '..', 'README.rst')
|
|
with open(path) as f:
|
|
contents = f.read()
|
|
send = [
|
|
@@ -90,7 +90,7 @@ class PostTest(unittest.TestCase):
|
|
]
|
|
expect = [{
|
|
'name': 'field2',
|
|
- 'filename': 'README',
|
|
+ 'filename': 'README.rst',
|
|
'data': contents,
|
|
}]
|
|
self.check_post(send, expect, 'http://localhost:8380/files')
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 1bcb3684a9ba30411c675ddc2e75e9a5a5def311 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:50:34 -0500
|
|
Subject: [PATCH 071/149] Python 2.5 compatibility: with statement
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 2 ++
|
|
tests/post_test.py | 2 ++
|
|
tests/write_to_file_test.py | 2 ++
|
|
3 files changed, 6 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index c0d256b..1d31e97 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -2,6 +2,8 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
+from __future__ import with_statement
|
|
+
|
|
import unittest
|
|
import pycurl
|
|
import sys
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index 6f9d8d4..804104e 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -2,6 +2,8 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
+from __future__ import with_statement
|
|
+
|
|
import os.path
|
|
import pycurl
|
|
import unittest
|
|
diff --git a/tests/write_to_file_test.py b/tests/write_to_file_test.py
|
|
index 67c9c63..c3c8822 100644
|
|
--- a/tests/write_to_file_test.py
|
|
+++ b/tests/write_to_file_test.py
|
|
@@ -2,6 +2,8 @@
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
+from __future__ import with_statement
|
|
+
|
|
import unittest
|
|
import pycurl
|
|
import tempfile
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 05d4fbe859d886ec0f0d104b5114a0f416021097 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:10:22 -0500
|
|
Subject: [PATCH 072/149] Python 2.5 compatibility: json/simplejson
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/app.py | 5 ++++-
|
|
tests/post_test.py | 5 ++++-
|
|
tests/post_with_read_callback_test.py | 5 ++++-
|
|
3 files changed, 12 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/tests/app.py b/tests/app.py
|
|
index a83e628..eb10668 100644
|
|
--- a/tests/app.py
|
|
+++ b/tests/app.py
|
|
@@ -1,5 +1,8 @@
|
|
import bottle
|
|
-import json
|
|
+try:
|
|
+ import json
|
|
+except ImportError:
|
|
+ import simplejson as json
|
|
|
|
app = bottle.Bottle()
|
|
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index 804104e..a36a677 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -8,7 +8,10 @@ import os.path
|
|
import pycurl
|
|
import unittest
|
|
import io
|
|
-import json
|
|
+try:
|
|
+ import json
|
|
+except ImportError:
|
|
+ import simplejson as json
|
|
try:
|
|
import urllib.parse as urllib_parse
|
|
except ImportError:
|
|
diff --git a/tests/post_with_read_callback_test.py b/tests/post_with_read_callback_test.py
|
|
index a09e83a..4d8f261 100644
|
|
--- a/tests/post_with_read_callback_test.py
|
|
+++ b/tests/post_with_read_callback_test.py
|
|
@@ -6,7 +6,10 @@ import os.path
|
|
import pycurl
|
|
import unittest
|
|
import io
|
|
-import json
|
|
+try:
|
|
+ import json
|
|
+except ImportError:
|
|
+ import simplejson as json
|
|
try:
|
|
import urllib.parse as urllib_parse
|
|
except ImportError:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From f29edfdd24ee3524a2674ba149c8a8d25741263c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:18:02 -0500
|
|
Subject: [PATCH 073/149] Python 2.5 compatibility: except as
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 4 +++-
|
|
1 files changed, 3 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index 5217a3f..8a978ec 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -1,5 +1,6 @@
|
|
# Run a WSGI application in a daemon thread
|
|
|
|
+import sys
|
|
import bottle
|
|
import threading
|
|
import socket
|
|
@@ -21,7 +22,8 @@ def wait_for_network_service(netloc, check_interval, num_attempts):
|
|
for i in range(num_attempts):
|
|
try:
|
|
conn = socket.create_connection(netloc, check_interval)
|
|
- except socket.error as e:
|
|
+ except socket.error:
|
|
+ e = sys.exc_info()[1]
|
|
_time.sleep(check_interval)
|
|
else:
|
|
conn.close()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 28f459a96fcc6c74afa50b7b3c01a2dd75bd59f8 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:23:08 -0500
|
|
Subject: [PATCH 074/149] Delete unused io imports
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 1 -
|
|
tests/header_function_test.py | 1 -
|
|
tests/post_test.py | 1 -
|
|
tests/post_with_read_callback_test.py | 1 -
|
|
tests/write_to_stringio_test.py | 1 -
|
|
5 files changed, 0 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index 1d31e97..27a3d04 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -8,7 +8,6 @@ import unittest
|
|
import pycurl
|
|
import sys
|
|
import tempfile
|
|
-import io
|
|
import os
|
|
|
|
from . import app
|
|
diff --git a/tests/header_function_test.py b/tests/header_function_test.py
|
|
index bfe7173..00080ba 100644
|
|
--- a/tests/header_function_test.py
|
|
+++ b/tests/header_function_test.py
|
|
@@ -4,7 +4,6 @@
|
|
|
|
import pycurl
|
|
import unittest
|
|
-import io
|
|
import time as _time
|
|
|
|
from . import app
|
|
diff --git a/tests/post_test.py b/tests/post_test.py
|
|
index a36a677..c11c3c8 100644
|
|
--- a/tests/post_test.py
|
|
+++ b/tests/post_test.py
|
|
@@ -7,7 +7,6 @@ from __future__ import with_statement
|
|
import os.path
|
|
import pycurl
|
|
import unittest
|
|
-import io
|
|
try:
|
|
import json
|
|
except ImportError:
|
|
diff --git a/tests/post_with_read_callback_test.py b/tests/post_with_read_callback_test.py
|
|
index 4d8f261..f0776ea 100644
|
|
--- a/tests/post_with_read_callback_test.py
|
|
+++ b/tests/post_with_read_callback_test.py
|
|
@@ -5,7 +5,6 @@
|
|
import os.path
|
|
import pycurl
|
|
import unittest
|
|
-import io
|
|
try:
|
|
import json
|
|
except ImportError:
|
|
diff --git a/tests/write_to_stringio_test.py b/tests/write_to_stringio_test.py
|
|
index 018800d..e9ab0c7 100644
|
|
--- a/tests/write_to_stringio_test.py
|
|
+++ b/tests/write_to_stringio_test.py
|
|
@@ -4,7 +4,6 @@
|
|
|
|
import pycurl
|
|
import unittest
|
|
-import io
|
|
|
|
from . import app
|
|
from . import runwsgi
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 8e2ee4ec10741ae7373f3c490df6696267871c12 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:54:35 -0500
|
|
Subject: [PATCH 075/149] Ignore fsync of stdout failures on travis
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/default_write_function_test.py | 13 +++++++++++--
|
|
1 files changed, 11 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/default_write_function_test.py b/tests/default_write_function_test.py
|
|
index 27a3d04..1c8ec16 100644
|
|
--- a/tests/default_write_function_test.py
|
|
+++ b/tests/default_write_function_test.py
|
|
@@ -18,6 +18,15 @@ setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
|
|
STDOUT_FD_NUM = 1
|
|
|
|
+def try_fsync(fd):
|
|
+ try:
|
|
+ os.fsync(fd)
|
|
+ except OSError:
|
|
+ # On travis:
|
|
+ # OSError: [Errno 22] Invalid argument
|
|
+ # ignore
|
|
+ pass
|
|
+
|
|
class DefaultWriteFunctionTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.curl = pycurl.Curl()
|
|
@@ -38,7 +47,7 @@ class DefaultWriteFunctionTest(unittest.TestCase):
|
|
# If this flush is not done, stdout output bleeds into the next test
|
|
# that is executed (without nose output capture)
|
|
sys.stdout.flush()
|
|
- os.fsync(STDOUT_FD_NUM)
|
|
+ try_fsync(STDOUT_FD_NUM)
|
|
|
|
# I have a really hard time getting this to work with nose output capture
|
|
def skip_perform_get_with_default_write_function(self):
|
|
@@ -67,7 +76,7 @@ class DefaultWriteFunctionTest(unittest.TestCase):
|
|
self.curl.perform()
|
|
sys.stdout.flush()
|
|
finally:
|
|
- os.fsync(STDOUT_FD_NUM)
|
|
+ try_fsync(STDOUT_FD_NUM)
|
|
os.dup2(saved_stdout_fd, STDOUT_FD_NUM)
|
|
os.close(saved_stdout_fd)
|
|
#os.dup2(100, 1)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From e7da1d864d955f21f31bdf880ed903abbee7c2ba Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 04:58:42 -0500
|
|
Subject: [PATCH 076/149] My vps says timeout might be -1 there
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_socket_select_test.py | 5 +++--
|
|
1 files changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/multi_socket_select_test.py b/tests/multi_socket_select_test.py
|
|
index 0c472cf..6db8b44 100644
|
|
--- a/tests/multi_socket_select_test.py
|
|
+++ b/tests/multi_socket_select_test.py
|
|
@@ -73,8 +73,9 @@ class MultiSocketSelectTest(unittest.TestCase):
|
|
|
|
timeout = m.timeout()
|
|
|
|
-
|
|
- while True:
|
|
+ # timeout might be -1, indicating that all work is done
|
|
+ # XXX make sure there is always work to be done here?
|
|
+ while timeout >= 0:
|
|
(rr, wr, er) = select.select(sockets,sockets,sockets,timeout/1000.0)
|
|
socketSet = set(rr+wr+er)
|
|
if socketSet:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From ee685a967f67e26ae32ec0c1d34fbad461fce2e7 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:14:57 -0500
|
|
Subject: [PATCH 077/149] Show pycurl versions in package setup
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/__init__.py | 4 ++++
|
|
1 files changed, 4 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/__init__.py b/tests/__init__.py
|
|
index e69de29..c1ff976 100644
|
|
--- a/tests/__init__.py
|
|
+++ b/tests/__init__.py
|
|
@@ -0,0 +1,4 @@
|
|
+import pycurl
|
|
+
|
|
+def setup_package():
|
|
+ print('Testing %s' % pycurl.version)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 359fc6e31a21620ea564288ae43ae23db35d1b2e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:07:19 -0500
|
|
Subject: [PATCH 078/149] Show what the entries are if assertion fails
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/debug_test.py | 3 ++-
|
|
1 files changed, 2 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/debug_test.py b/tests/debug_test.py
|
|
index 8005239..d74bed9 100644
|
|
--- a/tests/debug_test.py
|
|
+++ b/tests/debug_test.py
|
|
@@ -46,4 +46,5 @@ class DebugTest(unittest.TestCase):
|
|
for t, b in self.debug_entries:
|
|
if t == wanted_t and wanted_b in b:
|
|
return
|
|
- assert False, "%d: %s not found in debug entries" % (wanted_t, wanted_b)
|
|
+ assert False, "%d: %s not found in debug entries\nEntries are:\n%s" % \
|
|
+ (wanted_t, wanted_b, repr(self.debug_entries))
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 4c65d037fce349811d4954db137d0b3d5b3abe85 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:09:22 -0500
|
|
Subject: [PATCH 079/149] More informative failure message
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_test.py | 5 ++++-
|
|
1 files changed, 4 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index d9c6174..8701649 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -214,7 +214,10 @@ class MultiTest(unittest.TestCase):
|
|
self.assertEqual('success', m.handles[0].body.getvalue())
|
|
self.assertEqual(200, m.handles[0].http_code)
|
|
# bottle generated response body
|
|
- assert 'Error 403: Forbidden' in m.handles[1].body.getvalue()
|
|
+ body = m.handles[1].body.getvalue()
|
|
+ search = 'Error 403: Forbidden'
|
|
+ if search not in body:
|
|
+ assert False, "'%s' not found in body:\n%s" % (search, body)
|
|
self.assertEqual(403, m.handles[1].http_code)
|
|
# bottle generated response body
|
|
self.assertEqual('', m.handles[2].body.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 831b7a919d47b55e787c8af457b6ec815fca2035 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 06:34:39 -0500
|
|
Subject: [PATCH 080/149] Return complete response bodies for 403 and 404 responses as it looks like exact wording varies between bottle versions
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/app.py | 4 ++--
|
|
tests/multi_test.py | 9 +++------
|
|
2 files changed, 5 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/tests/app.py b/tests/app.py
|
|
index eb10668..9b56ace 100644
|
|
--- a/tests/app.py
|
|
+++ b/tests/app.py
|
|
@@ -12,11 +12,11 @@ def ok():
|
|
|
|
@app.route('/status/403')
|
|
def forbidden():
|
|
- bottle.abort(403, 'forbidden')
|
|
+ return bottle.HTTPResponse('forbidden', 403)
|
|
|
|
@app.route('/status/404')
|
|
def not_found():
|
|
- bottle.abort(404, 'not found')
|
|
+ return bottle.HTTPResponse('not found', 404)
|
|
|
|
@app.route('/postfields', method='post')
|
|
def postfields():
|
|
diff --git a/tests/multi_test.py b/tests/multi_test.py
|
|
index 8701649..d540413 100644
|
|
--- a/tests/multi_test.py
|
|
+++ b/tests/multi_test.py
|
|
@@ -153,10 +153,10 @@ class MultiTest(unittest.TestCase):
|
|
self.assertEqual('success', m.handles[0].body.getvalue())
|
|
self.assertEqual(200, m.handles[0].http_code)
|
|
# bottle generated response body
|
|
- assert 'Error 403: Forbidden' in m.handles[1].body.getvalue()
|
|
+ self.assertEqual('forbidden', m.handles[1].body.getvalue())
|
|
self.assertEqual(403, m.handles[1].http_code)
|
|
# bottle generated response body
|
|
- assert 'Error 404: Not Found' in m.handles[2].body.getvalue()
|
|
+ self.assertEqual('not found', m.handles[2].body.getvalue())
|
|
self.assertEqual(404, m.handles[2].http_code)
|
|
|
|
def check_adding_closed_handle(self, close_fn):
|
|
@@ -214,10 +214,7 @@ class MultiTest(unittest.TestCase):
|
|
self.assertEqual('success', m.handles[0].body.getvalue())
|
|
self.assertEqual(200, m.handles[0].http_code)
|
|
# bottle generated response body
|
|
- body = m.handles[1].body.getvalue()
|
|
- search = 'Error 403: Forbidden'
|
|
- if search not in body:
|
|
- assert False, "'%s' not found in body:\n%s" % (search, body)
|
|
+ self.assertEqual('forbidden', m.handles[1].body.getvalue())
|
|
self.assertEqual(403, m.handles[1].http_code)
|
|
# bottle generated response body
|
|
self.assertEqual('', m.handles[2].body.getvalue())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 6730160a7ede5c1bb490836cb42269d06a497dbe Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 22:15:47 -0500
|
|
Subject: [PATCH 081/149] Debug messages originated by curl 7.22 are different
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/debug_test.py | 6 +++++-
|
|
1 files changed, 5 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/debug_test.py b/tests/debug_test.py
|
|
index d74bed9..70e121c 100644
|
|
--- a/tests/debug_test.py
|
|
+++ b/tests/debug_test.py
|
|
@@ -32,7 +32,11 @@ class DebugTest(unittest.TestCase):
|
|
|
|
# Some checks with no particular intent
|
|
self.check(0, 'About to connect')
|
|
- self.check(0, 'Connected to localhost')
|
|
+ version = map(int, pycurl.version_info()[1].split('.'))
|
|
+ if version[0] < 7 or version[0] == 7 and version[1] <= 22:
|
|
+ self.check(0, 'connected')
|
|
+ else:
|
|
+ self.check(0, 'Connected to localhost')
|
|
self.check(0, 'port 8380')
|
|
# request
|
|
self.check(2, 'GET /success HTTP/1.1')
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 283ebc888e8016f575457db70a81eb46f219467c Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 22:17:48 -0500
|
|
Subject: [PATCH 082/149] Times in http headers are in UTC
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/header_function_test.py | 3 ++-
|
|
1 files changed, 2 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/header_function_test.py b/tests/header_function_test.py
|
|
index 00080ba..7ca564d 100644
|
|
--- a/tests/header_function_test.py
|
|
+++ b/tests/header_function_test.py
|
|
@@ -34,7 +34,8 @@ class HeaderFunctionTest(unittest.TestCase):
|
|
assert len(self.header_lines) > 0
|
|
self.assertEqual("HTTP/1.0 200 OK\r\n", self.header_lines[0])
|
|
# day of week
|
|
- todays_day = _time.strftime('%a')
|
|
+ # important: must be in utc
|
|
+ todays_day = _time.strftime('%a', _time.gmtime())
|
|
# Date: Sun, 03 Mar 2013 05:38:12 GMT\r\n
|
|
self.check('Date: %s' % todays_day)
|
|
# Server: WSGIServer/0.1 Python/2.7.3\r\n
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 0034724dd8ec8526f361c067d72e87c930f6eeb3 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 22:26:19 -0500
|
|
Subject: [PATCH 083/149] Create a generalized function for curl version comparisons
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/util.py | 15 +++++++++++++++
|
|
tests/version_comparison_test.py | 15 +++++++++++++++
|
|
2 files changed, 30 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/version_comparison_test.py
|
|
|
|
diff --git a/tests/util.py b/tests/util.py
|
|
index 891da44..46ac59f 100644
|
|
--- a/tests/util.py
|
|
+++ b/tests/util.py
|
|
@@ -3,6 +3,7 @@
|
|
# $Id$
|
|
|
|
import os, sys
|
|
+import pycurl
|
|
|
|
try:
|
|
from cStringIO import StringIO
|
|
@@ -12,6 +13,20 @@ except ImportError:
|
|
except ImportError:
|
|
from io import StringIO
|
|
|
|
+def version_less_than_spec(version_tuple, spec_tuple):
|
|
+ # spec_tuple may have 2 elements, expect version_tuple to have 3 elements
|
|
+ assert len(version_tuple) >= len(spec_tuple)
|
|
+ for i in range(len(spec_tuple)):
|
|
+ if version_tuple[i] < spec_tuple[i]:
|
|
+ return True
|
|
+ if version_tuple[i] > spec_tuple[i]:
|
|
+ return False
|
|
+ return False
|
|
+
|
|
+def pycurl_version_less_than(spec_tuple):
|
|
+ version = map(int, pycurl.version_info()[1].split('.'))
|
|
+ return version_less_than_spec(version, spec_tuple)
|
|
+
|
|
#
|
|
# prepare sys.path in case we are still in the build directory
|
|
# see also: distutils/command/build.py (build_platlib)
|
|
diff --git a/tests/version_comparison_test.py b/tests/version_comparison_test.py
|
|
new file mode 100644
|
|
index 0000000..80e780c
|
|
--- /dev/null
|
|
+++ b/tests/version_comparison_test.py
|
|
@@ -0,0 +1,15 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import unittest
|
|
+
|
|
+from . import util
|
|
+
|
|
+class VersionComparisonTest(unittest.TestCase):
|
|
+ def test_comparison(self):
|
|
+ assert util.version_less_than_spec((7, 22, 0), (7, 23, 0))
|
|
+ assert util.version_less_than_spec((7, 22, 0), (7, 23))
|
|
+ assert util.version_less_than_spec((7, 22, 0), (7, 22, 1))
|
|
+ assert not util.version_less_than_spec((7, 22, 0), (7, 22, 0))
|
|
+ assert not util.version_less_than_spec((7, 22, 0), (7, 22))
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d794edf43a119d4f600d3be8536c22419c9f4abb Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 22:27:25 -0500
|
|
Subject: [PATCH 084/149] Use version comparison helper in debug test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/debug_test.py | 3 +--
|
|
tests/util.py | 4 ++--
|
|
2 files changed, 3 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/tests/debug_test.py b/tests/debug_test.py
|
|
index 70e121c..e81d653 100644
|
|
--- a/tests/debug_test.py
|
|
+++ b/tests/debug_test.py
|
|
@@ -32,8 +32,7 @@ class DebugTest(unittest.TestCase):
|
|
|
|
# Some checks with no particular intent
|
|
self.check(0, 'About to connect')
|
|
- version = map(int, pycurl.version_info()[1].split('.'))
|
|
- if version[0] < 7 or version[0] == 7 and version[1] <= 22:
|
|
+ if util.pycurl_version_less_than(7, 24):
|
|
self.check(0, 'connected')
|
|
else:
|
|
self.check(0, 'Connected to localhost')
|
|
diff --git a/tests/util.py b/tests/util.py
|
|
index 46ac59f..b8e22ec 100644
|
|
--- a/tests/util.py
|
|
+++ b/tests/util.py
|
|
@@ -23,9 +23,9 @@ def version_less_than_spec(version_tuple, spec_tuple):
|
|
return False
|
|
return False
|
|
|
|
-def pycurl_version_less_than(spec_tuple):
|
|
+def pycurl_version_less_than(*spec):
|
|
version = map(int, pycurl.version_info()[1].split('.'))
|
|
- return version_less_than_spec(version, spec_tuple)
|
|
+ return version_less_than_spec(version, spec)
|
|
|
|
#
|
|
# prepare sys.path in case we are still in the build directory
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c1143004a0f27190fc4aec1228396db992f5c5de Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 6 Mar 2013 22:30:44 -0500
|
|
Subject: [PATCH 085/149] libcurl 7.23.0 produces different results
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_timer_test.py | 7 +++++--
|
|
1 files changed, 5 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/multi_timer_test.py b/tests/multi_timer_test.py
|
|
index e961780..c4b3df4 100644
|
|
--- a/tests/multi_timer_test.py
|
|
+++ b/tests/multi_timer_test.py
|
|
@@ -77,8 +77,11 @@ class MultiSocketTest(unittest.TestCase):
|
|
self.assertEqual(200, c.http_code)
|
|
|
|
assert len(timers) > 0
|
|
- assert timers[0] > 0
|
|
- self.assertEqual(-1, timers[-1])
|
|
+ # libcurl 7.23.0 produces a 0 timer
|
|
+ assert timers[0] >= 0
|
|
+ # this assertion does not appear to hold on older libcurls
|
|
+ if not util.pycurl_version_less_than(7, 24):
|
|
+ self.assertEqual(-1, timers[-1])
|
|
|
|
# close handles
|
|
for c in m.handles:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From abc0199b4b2517a82c492cd3f64f10883a5ec257 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 7 Mar 2013 00:16:21 -0500
|
|
Subject: [PATCH 086/149] Change memleak test to use id() rather than regexp match of addresses (closes #12)
|
|
|
|
This commit also fixes the test to check objects that GC tracks
|
|
rather than the object type repeatedly.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/memleak_test.py | 16 ++++++----------
|
|
1 files changed, 6 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/tests/memleak_test.py b/tests/memleak_test.py
|
|
index 6e9f76c..1b1bbd5 100644
|
|
--- a/tests/memleak_test.py
|
|
+++ b/tests/memleak_test.py
|
|
@@ -5,12 +5,9 @@
|
|
import pycurl
|
|
import unittest
|
|
import gc
|
|
-import re
|
|
|
|
class MemleakTest(unittest.TestCase):
|
|
def test_collection(self):
|
|
- regexp = re.compile(r'at (0x\d+)')
|
|
-
|
|
gc.collect()
|
|
flags = gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE
|
|
# python 3 has no DEBUG_OBJECTS
|
|
@@ -31,12 +28,10 @@ class MemleakTest(unittest.TestCase):
|
|
multi.add_handle(curl)
|
|
t.append(curl)
|
|
|
|
- match = regexp.search(repr(curl))
|
|
- assert match is not None
|
|
- searches.append(match.group(1))
|
|
- match = regexp.search(repr(multi))
|
|
- assert match
|
|
- searches.append(match.group(1))
|
|
+ c_id = id(curl)
|
|
+ searches.append(c_id)
|
|
+ m_id = id(multi)
|
|
+ searches.append(m_id)
|
|
|
|
#print("Tracked objects:", len(gc.get_objects()))
|
|
|
|
@@ -56,4 +51,5 @@ class MemleakTest(unittest.TestCase):
|
|
|
|
objects = gc.get_objects()
|
|
for search in searches:
|
|
- assert 'at %s' % search not in repr(object)
|
|
+ for object in objects:
|
|
+ assert search != id(object)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 14dd7fdbe5697f7e7349cbe44258f41f74455fc0 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Mon, 11 Mar 2013 22:19:14 -0400
|
|
Subject: [PATCH 087/149] More informative exception message when vsftpd is missing or not in PATH (closes #6)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/procmgr.py | 12 +++++++++++-
|
|
1 files changed, 11 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/procmgr.py b/tests/procmgr.py
|
|
index 8d5c0cc..ce08da9 100644
|
|
--- a/tests/procmgr.py
|
|
+++ b/tests/procmgr.py
|
|
@@ -1,6 +1,7 @@
|
|
import threading
|
|
import subprocess
|
|
import os
|
|
+import sys
|
|
import signal
|
|
|
|
from . import runwsgi
|
|
@@ -53,7 +54,16 @@ def vsftpd_setup():
|
|
]
|
|
setup_module = start_setup(cmd)
|
|
def do_setup_module():
|
|
- setup_module()
|
|
+ try:
|
|
+ setup_module()
|
|
+ except OSError:
|
|
+ import errno
|
|
+ e = sys.exc_info()[1]
|
|
+ if e.errno == errno.ENOENT:
|
|
+ msg = "Tried to execute `%s`\nTry specifying path to vsftpd via PYCURL_VSFTPD_PATH environment variable\n" % vsftpd_path
|
|
+ raise OSError(e.errno, e.strerror + "\n" + msg)
|
|
+ else:
|
|
+ raise
|
|
ok = runwsgi.wait_for_network_service(('127.0.0.1', 8321), 0.1, 10)
|
|
if not ok:
|
|
import warnings
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 1505197b9eb8d5ccbc3d039866e87d522455d9d0 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Mon, 11 Mar 2013 22:22:02 -0400
|
|
Subject: [PATCH 088/149] Delete -1 timer assertion from multi timer test (closes #19)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_timer_test.py | 6 ++++--
|
|
1 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/multi_timer_test.py b/tests/multi_timer_test.py
|
|
index c4b3df4..ff856d7 100644
|
|
--- a/tests/multi_timer_test.py
|
|
+++ b/tests/multi_timer_test.py
|
|
@@ -80,8 +80,10 @@ class MultiSocketTest(unittest.TestCase):
|
|
# libcurl 7.23.0 produces a 0 timer
|
|
assert timers[0] >= 0
|
|
# this assertion does not appear to hold on older libcurls
|
|
- if not util.pycurl_version_less_than(7, 24):
|
|
- self.assertEqual(-1, timers[-1])
|
|
+ # or apparently on any linuxes, see
|
|
+ # https://github.com/p/pycurl/issues/19
|
|
+ #if not util.pycurl_version_less_than(7, 24):
|
|
+ # self.assertEqual(-1, timers[-1])
|
|
|
|
# close handles
|
|
for c in m.handles:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 041b4666519f3fa2594f5ee919e62006cb8ae2f1 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Mon, 11 Mar 2013 14:00:04 +0100
|
|
Subject: [PATCH 089/149] remove .cvsignore files, add *.pyc and *.pyo to .gitignore
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.gitignore | 2 ++
|
|
1 files changed, 2 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/.gitignore b/.gitignore
|
|
index 796b96d..899daba 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -1 +1,3 @@
|
|
+*.pyc
|
|
+*.pyo
|
|
/build
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 3dc27e280021512e84cd77f68c7ff3d4e5cb2ae0 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Mon, 11 Mar 2013 22:40:12 -0400
|
|
Subject: [PATCH 090/149] Readd cvsignore contents and empty directories
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.gitignore | 6 ++++++
|
|
1 files changed, 6 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/.gitignore b/.gitignore
|
|
index 899daba..c873e32 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -1,3 +1,9 @@
|
|
*.pyc
|
|
*.pyo
|
|
+/MANIFEST
|
|
/build
|
|
+/dist
|
|
+/www/htdocs/download/*.bz2
|
|
+/www/htdocs/download/*.exe
|
|
+/www/htdocs/download/*.gz
|
|
+/www/upload/*
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d6c800cdc963e349921cae8ac10df9f9f23cac79 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Mon, 11 Mar 2013 14:03:06 +0100
|
|
Subject: [PATCH 091/149] vsftpd.conf: add background=no to allow for proper shutdown
|
|
|
|
When the "background" directive in the vsftpd.conf configuration file is
|
|
set to "YES", the vsftpd startup script forks, creating a child process
|
|
(the vsftpd daemon) which immediately sends the SIGUSR1 signal to its
|
|
parent process, which exits upon receiving it. The teardown routine in
|
|
procmgr.py would then send the SIGTERM signal to a process that does not
|
|
exist anymore.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/vsftpd.conf | 1 +
|
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/tests/vsftpd.conf b/tests/vsftpd.conf
|
|
index 0abb39f..b4e4972 100644
|
|
--- a/tests/vsftpd.conf
|
|
+++ b/tests/vsftpd.conf
|
|
@@ -1,5 +1,6 @@
|
|
anon_world_readable_only=yes
|
|
anonymous_enable=yes
|
|
+background=no
|
|
# currently we only list files
|
|
download_enable=no
|
|
listen=yes
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 8acdaaf5c311038a5dd7fcd81f13c0bb984b66c7 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Tue, 26 Feb 2013 14:49:47 +0100
|
|
Subject: [PATCH 092/149] pycurl.c: eliminate duplicated code in util_write_callback()
|
|
|
|
Suggested by Zdenek Pavlas <https://bugzilla.redhat.com/857875#c8>.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 10 +---------
|
|
1 files changed, 1 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 094bc60..f701543 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -1082,15 +1082,7 @@ util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *strea
|
|
if (result == Py_None) {
|
|
ret = total_size; /* None means success */
|
|
}
|
|
- else if (PyInt_Check(result)) {
|
|
- long obj_size = PyInt_AsLong(result);
|
|
- if (obj_size < 0 || obj_size > total_size) {
|
|
- PyErr_Format(ErrorObject, "invalid return value for write callback %ld %ld", (long)obj_size, (long)total_size);
|
|
- goto verbose_error;
|
|
- }
|
|
- ret = (size_t) obj_size; /* success */
|
|
- }
|
|
- else if (PyLong_Check(result)) {
|
|
+ else if (PyInt_Check(result) || PyLong_Check(result)) {
|
|
long obj_size = PyLong_AsLong(result);
|
|
if (obj_size < 0 || obj_size > total_size) {
|
|
PyErr_Format(ErrorObject, "invalid return value for write callback %ld %ld", (long)obj_size, (long)total_size);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From b55c2cab56733a86b4ebc5ccccdf8c5530bca85a Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Tue, 26 Feb 2013 16:58:55 +0100
|
|
Subject: [PATCH 093/149] pycurl.c: allow to return -1 from write callback
|
|
|
|
... to abort the transfer and WRITEFUNC_PAUSE to pause the transfer
|
|
|
|
Reported By: Zdenek Pavlas
|
|
Bug: https://bugzilla.redhat.com/857875
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 11 +++++------
|
|
1 files changed, 5 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index f701543..a30c339 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -1083,12 +1083,8 @@ util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *strea
|
|
ret = total_size; /* None means success */
|
|
}
|
|
else if (PyInt_Check(result) || PyLong_Check(result)) {
|
|
- long obj_size = PyLong_AsLong(result);
|
|
- if (obj_size < 0 || obj_size > total_size) {
|
|
- PyErr_Format(ErrorObject, "invalid return value for write callback %ld %ld", (long)obj_size, (long)total_size);
|
|
- goto verbose_error;
|
|
- }
|
|
- ret = (size_t) obj_size; /* success */
|
|
+ /* if the cast to long fails, PyLong_AsLong() returns -1L */
|
|
+ ret = (size_t) PyLong_AsLong(result);
|
|
}
|
|
else {
|
|
PyErr_SetString(ErrorObject, "write callback must return int or None");
|
|
@@ -3509,6 +3505,9 @@ initpycurl(void)
|
|
/* Abort curl_read_callback(). */
|
|
insint_c(d, "READFUNC_ABORT", CURL_READFUNC_ABORT);
|
|
|
|
+ /* Pause curl_write_callback(). */
|
|
+ insint_c(d, "WRITEFUNC_PAUSE", CURL_WRITEFUNC_PAUSE);
|
|
+
|
|
/* constants for ioctl callback return values */
|
|
insint_c(d, "IOE_OK", CURLIOE_OK);
|
|
insint_c(d, "IOE_UNKNOWNCMD", CURLIOE_UNKNOWNCMD);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 32664e552084fad471de98f219f58c52c95653f4 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Wed, 6 Mar 2013 14:38:01 +0100
|
|
Subject: [PATCH 094/149] write_abort_test.py: test returning -1 from write callback
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/write_abort_test.py | 35 +++++++++++++++++++++++++++++++++++
|
|
1 files changed, 35 insertions(+), 0 deletions(-)
|
|
create mode 100755 tests/write_abort_test.py
|
|
|
|
diff --git a/tests/write_abort_test.py b/tests/write_abort_test.py
|
|
new file mode 100755
|
|
index 0000000..73e8245
|
|
--- /dev/null
|
|
+++ b/tests/write_abort_test.py
|
|
@@ -0,0 +1,35 @@
|
|
+#!/usr/bin/python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import os.path
|
|
+import pycurl
|
|
+import sys
|
|
+import unittest
|
|
+
|
|
+class WriteAbortTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ pycurl.global_init(pycurl.GLOBAL_DEFAULT)
|
|
+
|
|
+ def tearDown(self):
|
|
+ pycurl.global_cleanup()
|
|
+
|
|
+ def test_write_abort(self):
|
|
+ def write_cb(_):
|
|
+ # this should cause pycurl.WRITEFUNCTION (without any range errors)
|
|
+ return -1
|
|
+
|
|
+ # download the script itself through the file:// protocol into write_cb
|
|
+ c = pycurl.Curl()
|
|
+ c.setopt(pycurl.URL, 'file://' + os.path.abspath(sys.argv[0]))
|
|
+ c.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
+ try:
|
|
+ c.perform()
|
|
+ except pycurl.error, (err, msg):
|
|
+ # we expect pycurl.E_WRITE_ERROR as the response
|
|
+ assert pycurl.E_WRITE_ERROR == err
|
|
+
|
|
+ # no additional errors should be reported
|
|
+ assert not hasattr(sys, 'last_value')
|
|
+
|
|
+ c.close()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 808c5b785ccd2f3bcca15146ae998a8609229b38 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Mon, 11 Mar 2013 23:48:10 -0400
|
|
Subject: [PATCH 095/149] setup/teardown consistent with other tests
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/write_abort_test.py | 13 +++++--------
|
|
1 files changed, 5 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/tests/write_abort_test.py b/tests/write_abort_test.py
|
|
index 73e8245..f720882 100755
|
|
--- a/tests/write_abort_test.py
|
|
+++ b/tests/write_abort_test.py
|
|
@@ -9,10 +9,10 @@ import unittest
|
|
|
|
class WriteAbortTest(unittest.TestCase):
|
|
def setUp(self):
|
|
- pycurl.global_init(pycurl.GLOBAL_DEFAULT)
|
|
+ self.curl = pycurl.Curl()
|
|
|
|
def tearDown(self):
|
|
- pycurl.global_cleanup()
|
|
+ self.curl.close()
|
|
|
|
def test_write_abort(self):
|
|
def write_cb(_):
|
|
@@ -20,16 +20,13 @@ class WriteAbortTest(unittest.TestCase):
|
|
return -1
|
|
|
|
# download the script itself through the file:// protocol into write_cb
|
|
- c = pycurl.Curl()
|
|
- c.setopt(pycurl.URL, 'file://' + os.path.abspath(sys.argv[0]))
|
|
- c.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
+ self.curl.setopt(pycurl.URL, 'file://' + os.path.abspath(sys.argv[0]))
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
try:
|
|
- c.perform()
|
|
+ self.curl.perform()
|
|
except pycurl.error, (err, msg):
|
|
# we expect pycurl.E_WRITE_ERROR as the response
|
|
assert pycurl.E_WRITE_ERROR == err
|
|
|
|
# no additional errors should be reported
|
|
assert not hasattr(sys, 'last_value')
|
|
-
|
|
- c.close()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c662b504c202ca434d723de3984c12a35358e9f8 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Mon, 11 Mar 2013 23:48:41 -0400
|
|
Subject: [PATCH 096/149] Correct shebang
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/write_abort_test.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/write_abort_test.py b/tests/write_abort_test.py
|
|
index f720882..3272961 100755
|
|
--- a/tests/write_abort_test.py
|
|
+++ b/tests/write_abort_test.py
|
|
@@ -1,4 +1,4 @@
|
|
-#!/usr/bin/python
|
|
+#! /usr/bin/env python
|
|
# -*- coding: iso-8859-1 -*-
|
|
# vi:ts=4:et
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 43d385231293a22fb65490db8348c9a18592c7b0 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Mon, 11 Mar 2013 23:56:36 -0400
|
|
Subject: [PATCH 097/149] Check that bogus return values from write callback are correctly handled (still)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/write_cb_bogus_test.py | 44 ++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 44 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/write_cb_bogus_test.py
|
|
|
|
diff --git a/tests/write_cb_bogus_test.py b/tests/write_cb_bogus_test.py
|
|
new file mode 100644
|
|
index 0000000..4bec2ad
|
|
--- /dev/null
|
|
+++ b/tests/write_cb_bogus_test.py
|
|
@@ -0,0 +1,44 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import os.path
|
|
+import pycurl
|
|
+import sys
|
|
+import unittest
|
|
+
|
|
+class WriteAbortTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def write_cb_returning_string(self, data):
|
|
+ return 'foo'
|
|
+
|
|
+ def write_cb_returning_float(self, data):
|
|
+ return 0.5
|
|
+
|
|
+ def test_write_cb_returning_string(self):
|
|
+ self.check(self.write_cb_returning_string)
|
|
+
|
|
+ def test_write_cb_returning_float(self):
|
|
+ self.check(self.write_cb_returning_float)
|
|
+
|
|
+ def check(self, write_cb):
|
|
+ # download the script itself through the file:// protocol into write_cb
|
|
+ c = pycurl.Curl()
|
|
+ self.curl.setopt(pycurl.URL, 'file://' + os.path.abspath(sys.argv[0]))
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
+ try:
|
|
+ self.curl.perform()
|
|
+ except pycurl.error, (err, msg):
|
|
+ # we expect pycurl.E_WRITE_ERROR as the response
|
|
+ assert pycurl.E_WRITE_ERROR == err
|
|
+
|
|
+ # actual error
|
|
+ assert hasattr(sys, 'last_type')
|
|
+ self.assertEqual(pycurl.error, sys.last_type)
|
|
+ assert hasattr(sys, 'last_value')
|
|
+ self.assertEqual('write callback must return int or None', str(sys.last_value))
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c04e16173e67b91c47018a5f023d703f751ba23e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 12 Mar 2013 00:00:40 -0400
|
|
Subject: [PATCH 098/149] Fix mode on write abort test
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
0 files changed, 0 insertions(+), 0 deletions(-)
|
|
mode change 100755 => 100644 tests/write_abort_test.py
|
|
|
|
diff --git a/tests/write_abort_test.py b/tests/write_abort_test.py
|
|
old mode 100755
|
|
new mode 100644
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From a14d3afd57c9a402e8256a53cdcc389008356f3e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 12 Mar 2013 00:02:56 -0400
|
|
Subject: [PATCH 099/149] This test fails intermittently, add diagnostics
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/multi_socket_select_test.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/multi_socket_select_test.py b/tests/multi_socket_select_test.py
|
|
index 6db8b44..9546169 100644
|
|
--- a/tests/multi_socket_select_test.py
|
|
+++ b/tests/multi_socket_select_test.py
|
|
@@ -94,7 +94,7 @@ class MultiSocketSelectTest(unittest.TestCase):
|
|
c.http_code = c.getinfo(c.HTTP_CODE)
|
|
|
|
# at least in and remove events per socket
|
|
- assert len(socket_events) >= 6
|
|
+ assert len(socket_events) >= 6, 'Less than 6 socket events: %s' % repr(socket_events)
|
|
|
|
# print result
|
|
for c in m.handles:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2af85c62b266127bd9e58d1df2b1fb079a0e9654 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 12 Mar 2013 22:43:47 -0400
|
|
Subject: [PATCH 100/149] Python 2.5 compatibility: socket.create_connection
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 14 +++++++++++++-
|
|
1 files changed, 13 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index 8a978ec..be05dfa 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -6,6 +6,18 @@ import threading
|
|
import socket
|
|
import time as _time
|
|
|
|
+try:
|
|
+ create_connection = socket.create_connection
|
|
+except AttributeError:
|
|
+ # python 2.5
|
|
+ def create_connection(netloc, timeout=None):
|
|
+ # XXX ipv4 only
|
|
+ s = socket.socket()
|
|
+ if timeout is not None:
|
|
+ s.settimeout(timeout)
|
|
+ s.connect(netloc)
|
|
+ return s
|
|
+
|
|
class Server(bottle.WSGIRefServer):
|
|
def run(self, handler): # pragma: no cover
|
|
from wsgiref.simple_server import make_server, WSGIRequestHandler
|
|
@@ -21,7 +33,7 @@ def wait_for_network_service(netloc, check_interval, num_attempts):
|
|
ok = False
|
|
for i in range(num_attempts):
|
|
try:
|
|
- conn = socket.create_connection(netloc, check_interval)
|
|
+ conn = create_connection(netloc, check_interval)
|
|
except socket.error:
|
|
e = sys.exc_info()[1]
|
|
_time.sleep(check_interval)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d1c79723cecd7ee75181f29b46081fc49ea28790 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 12 Mar 2013 22:55:08 -0400
|
|
Subject: [PATCH 101/149] Python 2.5 compatibility: poll_interval in SocketServer
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 17 +++++++++++++++--
|
|
1 files changed, 15 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index be05dfa..114ce42 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -18,6 +18,8 @@ except AttributeError:
|
|
s.connect(netloc)
|
|
return s
|
|
|
|
+global_stop = False
|
|
+
|
|
class Server(bottle.WSGIRefServer):
|
|
def run(self, handler): # pragma: no cover
|
|
from wsgiref.simple_server import make_server, WSGIRequestHandler
|
|
@@ -27,7 +29,13 @@ class Server(bottle.WSGIRefServer):
|
|
def log_request(*args, **kw): pass
|
|
self.options['handler_class'] = QuietHandler
|
|
self.srv = make_server(self.host, self.port, handler, **self.options)
|
|
- self.srv.serve_forever(poll_interval=0.1)
|
|
+ if sys.version_info[0] == 2 and sys.version_info[1] < 6:
|
|
+ # python 2.5 has no poll_interval
|
|
+ # and thus no way to stop the server
|
|
+ while not global_stop:
|
|
+ self.srv.handle_request()
|
|
+ else:
|
|
+ self.srv.serve_forever(poll_interval=0.1)
|
|
|
|
def wait_for_network_service(netloc, check_interval, num_attempts):
|
|
ok = False
|
|
@@ -104,6 +112,11 @@ def app_runner_setup(*specs):
|
|
for server in self.servers:
|
|
# if no tests from module were run, there is no server to shut down
|
|
if hasattr(server, 'srv'):
|
|
- server.srv.shutdown()
|
|
+ if hasattr(server.srv, 'shutdown'):
|
|
+ server.srv.shutdown()
|
|
+ else:
|
|
+ # python 2.5
|
|
+ global global_stop
|
|
+ global_stop = True
|
|
|
|
return [setup, teardown]
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From cb24d7050133cbed97c7f05ef6f649c7a7bfede3 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 15 Mar 2013 12:28:11 -0400
|
|
Subject: [PATCH 102/149] Tests do not call global cleanup for now
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/reset_test.py | 2 --
|
|
1 files changed, 0 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/reset_test.py b/tests/reset_test.py
|
|
index cc55f86..61a692a 100644
|
|
--- a/tests/reset_test.py
|
|
+++ b/tests/reset_test.py
|
|
@@ -72,5 +72,3 @@ class ResetTest(unittest.TestCase):
|
|
eh.close()
|
|
cm.close()
|
|
outf.close()
|
|
-
|
|
- pycurl.global_cleanup()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 7a74c1e39377d4220ffafe335a71487515bede8e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 15 Mar 2013 17:01:35 -0400
|
|
Subject: [PATCH 103/149] Python 3 compatibility: except syntax
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/write_abort_test.py | 3 ++-
|
|
tests/write_cb_bogus_test.py | 3 ++-
|
|
2 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/tests/write_abort_test.py b/tests/write_abort_test.py
|
|
index 3272961..957fe78 100644
|
|
--- a/tests/write_abort_test.py
|
|
+++ b/tests/write_abort_test.py
|
|
@@ -24,7 +24,8 @@ class WriteAbortTest(unittest.TestCase):
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
try:
|
|
self.curl.perform()
|
|
- except pycurl.error, (err, msg):
|
|
+ except pycurl.error:
|
|
+ err, msg = sys.exc_info()[1]
|
|
# we expect pycurl.E_WRITE_ERROR as the response
|
|
assert pycurl.E_WRITE_ERROR == err
|
|
|
|
diff --git a/tests/write_cb_bogus_test.py b/tests/write_cb_bogus_test.py
|
|
index 4bec2ad..ef709db 100644
|
|
--- a/tests/write_cb_bogus_test.py
|
|
+++ b/tests/write_cb_bogus_test.py
|
|
@@ -33,7 +33,8 @@ class WriteAbortTest(unittest.TestCase):
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
try:
|
|
self.curl.perform()
|
|
- except pycurl.error, (err, msg):
|
|
+ except pycurl.error:
|
|
+ err, msg = sys.exc_info()[1]
|
|
# we expect pycurl.E_WRITE_ERROR as the response
|
|
assert pycurl.E_WRITE_ERROR == err
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 84bb12176059f28c0cc030d6b620656a00fff3a4 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 15 Mar 2013 21:21:50 -0400
|
|
Subject: [PATCH 104/149] Python 3 compatibility: map
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/util.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/util.py b/tests/util.py
|
|
index b8e22ec..1e9f406 100644
|
|
--- a/tests/util.py
|
|
+++ b/tests/util.py
|
|
@@ -24,7 +24,7 @@ def version_less_than_spec(version_tuple, spec_tuple):
|
|
return False
|
|
|
|
def pycurl_version_less_than(*spec):
|
|
- version = map(int, pycurl.version_info()[1].split('.'))
|
|
+ version = [int(part) for part in pycurl.version_info()[1].split('.')]
|
|
return version_less_than_spec(version, spec)
|
|
|
|
#
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d30ec2cf96c66cd176bb999fb7a3a39d13ddf0dd Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 15 Mar 2013 21:27:58 -0400
|
|
Subject: [PATCH 105/149] Python 3 compatibility: apply no longer exists
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
python/curl/__init__.py | 4 ++--
|
|
setup.py | 3 +--
|
|
setup_win32_ssl.py | 2 +-
|
|
3 files changed, 4 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/python/curl/__init__.py b/python/curl/__init__.py
|
|
index b002618..5b6b549 100644
|
|
--- a/python/curl/__init__.py
|
|
+++ b/python/curl/__init__.py
|
|
@@ -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."
|
|
@@ -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."
|
|
diff --git a/setup.py b/setup.py
|
|
index 235e4c9..013bd11 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -221,5 +221,4 @@ if LooseVersion(distutils.__version__) < LooseVersion("1.0.3"):
|
|
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/setup_win32_ssl.py b/setup_win32_ssl.py
|
|
index 332c04c..0ecc399 100644
|
|
--- a/setup_win32_ssl.py
|
|
+++ b/setup_win32_ssl.py
|
|
@@ -32,5 +32,5 @@ ext.extra_objects.append(r"c:\src\pool\libidn-0.5.15" + pool + "idn.lib")
|
|
if __name__ == "__main__":
|
|
for o in ext.extra_objects:
|
|
assert os.path.isfile(o), o
|
|
- apply(setup, (), setup_args)
|
|
+ setup(**setup_args)
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c903dc9eebdf010bfc8142b5f47cd564e04baa19 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 26 Feb 2013 16:40:28 -0500
|
|
Subject: [PATCH 106/149] Python 3 compatibility: exception raising syntax
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
setup.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/setup.py b/setup.py
|
|
index 013bd11..725007c 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -108,7 +108,7 @@ else:
|
|
if p.wait() == 0:
|
|
optbuf += stdout
|
|
if optbuf == "":
|
|
- raise Exception, ("Neither of curl-config --libs or --static-libs" +
|
|
+ raise Exception("Neither of curl-config --libs or --static-libs" +
|
|
"produced output")
|
|
libs = split_quoted(optbuf)
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2643ab0cd015f09b1a0fd928c8e1102eee8e203e Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 27 Feb 2013 20:23:28 -0500
|
|
Subject: [PATCH 107/149] Python 3 compatibility: print syntax (src)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
python/curl/__init__.py | 8 ++++----
|
|
1 files changed, 4 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/python/curl/__init__.py b/python/curl/__init__.py
|
|
index 5b6b549..5617262 100644
|
|
--- a/python/curl/__init__.py
|
|
+++ b/python/curl/__init__.py
|
|
@@ -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()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From c2f5306b77da24f1cb1cf45b9dbda93b817bf6e6 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 26 Feb 2013 16:49:09 -0500
|
|
Subject: [PATCH 108/149] Python 3 compatibility: print syntax (former tests)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
examples/tests/test_gtk.py | 2 +-
|
|
examples/tests/test_xmlrpc.py | 2 +-
|
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/examples/tests/test_gtk.py b/examples/tests/test_gtk.py
|
|
index 7104439..da8c22a 100644
|
|
--- a/examples/tests/test_gtk.py
|
|
+++ b/examples/tests/test_gtk.py
|
|
@@ -83,7 +83,7 @@ class Test(threading.Thread):
|
|
|
|
# Check command line args
|
|
if len(sys.argv) < 3:
|
|
- print "Usage: %s <URL> <filename>" % sys.argv[0]
|
|
+ print("Usage: %s <URL> <filename>" % sys.argv[0])
|
|
raise SystemExit
|
|
|
|
# Make a progress bar window
|
|
diff --git a/examples/tests/test_xmlrpc.py b/examples/tests/test_xmlrpc.py
|
|
index bc5953e..3a5469a 100644
|
|
--- a/examples/tests/test_xmlrpc.py
|
|
+++ b/examples/tests/test_xmlrpc.py
|
|
@@ -24,6 +24,6 @@ c.setopt(c.POST, 1)
|
|
c.setopt(c.HTTPHEADER, xmlrpc_header)
|
|
c.setopt(c.POSTFIELDS, xmlrpc_template % ("examples.getStateName", xmlrpclib.dumps((5,))))
|
|
|
|
-print 'Response from http://betty.userland.com/'
|
|
+print('Response from http://betty.userland.com/')
|
|
c.perform()
|
|
c.close()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 0106dfe86ca2a5620f07c2687cb05502636298ce Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 27 Feb 2013 20:23:39 -0500
|
|
Subject: [PATCH 109/149] Python 3 compatibility: print syntax (examples)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
examples/basicfirst.py | 4 +-
|
|
examples/file_upload.py | 6 +-
|
|
examples/linksys.py | 182 +++++++++++++++++++++---------------------
|
|
examples/retriever-multi.py | 10 +-
|
|
examples/retriever.py | 6 +-
|
|
examples/sfquery.py | 2 +-
|
|
examples/xmlrpc_curl.py | 6 +-
|
|
7 files changed, 108 insertions(+), 108 deletions(-)
|
|
|
|
diff --git a/examples/basicfirst.py b/examples/basicfirst.py
|
|
index af59405..44060af 100644
|
|
--- a/examples/basicfirst.py
|
|
+++ b/examples/basicfirst.py
|
|
@@ -13,7 +13,7 @@ class Test:
|
|
def body_callback(self, buf):
|
|
self.contents = self.contents + buf
|
|
|
|
-print >>sys.stderr, 'Testing', pycurl.version
|
|
+sys.stderr.write("Testing %s\n" % pycurl.version)
|
|
|
|
t = Test()
|
|
c = pycurl.Curl()
|
|
@@ -22,4 +22,4 @@ c.setopt(c.WRITEFUNCTION, t.body_callback)
|
|
c.perform()
|
|
c.close()
|
|
|
|
-print t.contents
|
|
+print(t.contents)
|
|
diff --git a/examples/file_upload.py b/examples/file_upload.py
|
|
index a514c1c..7750865 100644
|
|
--- a/examples/file_upload.py
|
|
+++ b/examples/file_upload.py
|
|
@@ -15,13 +15,13 @@ class FileReader:
|
|
|
|
# Check commandline arguments
|
|
if len(sys.argv) < 3:
|
|
- print "Usage: %s <url> <file to upload>" % sys.argv[0]
|
|
+ print("Usage: %s <url> <file to upload>" % sys.argv[0])
|
|
raise SystemExit
|
|
url = sys.argv[1]
|
|
filename = sys.argv[2]
|
|
|
|
if not os.path.exists(filename):
|
|
- print "Error: the file '%s' does not exist" % filename
|
|
+ print("Error: the file '%s' does not exist" % filename)
|
|
raise SystemExit
|
|
|
|
# Initialize pycurl
|
|
@@ -41,6 +41,6 @@ filesize = os.path.getsize(filename)
|
|
c.setopt(pycurl.INFILESIZE, filesize)
|
|
|
|
# Start transfer
|
|
-print 'Uploading file %s to url %s' % (filename, url)
|
|
+print('Uploading file %s to url %s' % (filename, url))
|
|
c.perform()
|
|
c.close()
|
|
diff --git a/examples/linksys.py b/examples/linksys.py
|
|
index 5304886..24cb2a9 100755
|
|
--- a/examples/linksys.py
|
|
+++ b/examples/linksys.py
|
|
@@ -224,11 +224,11 @@ if __name__ == "__main__":
|
|
self.session = LinksysSession()
|
|
if os.isatty(0):
|
|
import readline
|
|
- print "Type ? or `help' for help."
|
|
+ print("Type ? or `help' for help.")
|
|
self.prompt = self.session.host + ": "
|
|
else:
|
|
self.prompt = ""
|
|
- print "Bar1"
|
|
+ print("Bar1")
|
|
|
|
def flag_command(self, func, line):
|
|
if line.strip() in ("on", "enable", "yes"):
|
|
@@ -246,96 +246,96 @@ if __name__ == "__main__":
|
|
self.session.cache_flush()
|
|
self.prompt = self.session.host + ": "
|
|
else:
|
|
- print self.session.host
|
|
+ print(self.session.host)
|
|
return 0
|
|
def help_connect(self):
|
|
- print "Usage: connect [<hostname-or-IP>]"
|
|
- print "Connect to a Linksys by name or IP address."
|
|
- print "If no argument is given, print the current host."
|
|
+ print("Usage: connect [<hostname-or-IP>]")
|
|
+ print("Connect to a Linksys by name or IP address.")
|
|
+ print("If no argument is given, print the current host.")
|
|
|
|
def do_status(self, line):
|
|
self.session.cache_load("")
|
|
if "" in self.session.pagecache:
|
|
- print "Firmware:", self.session.get_firmware_version()
|
|
- print "LAN MAC:", self.session.get_LAN_MAC()
|
|
- print "Wireless MAC:", self.session.get_Wireless_MAC()
|
|
- print "WAN MAC:", self.session.get_WAN_MAC()
|
|
- print "."
|
|
+ print("Firmware:", self.session.get_firmware_version())
|
|
+ print("LAN MAC:", self.session.get_LAN_MAC())
|
|
+ print("Wireless MAC:", self.session.get_Wireless_MAC())
|
|
+ print("WAN MAC:", self.session.get_WAN_MAC())
|
|
+ print(".")
|
|
return 0
|
|
def help_status(self):
|
|
- print "Usage: status"
|
|
- print "The status command shows the status of the Linksys."
|
|
- print "It is mainly useful as a sanity check to make sure"
|
|
- print "the box is responding correctly."
|
|
+ print("Usage: status")
|
|
+ print("The status command shows the status of the Linksys.")
|
|
+ print("It is mainly useful as a sanity check to make sure")
|
|
+ print("the box is responding correctly.")
|
|
|
|
def do_verbose(self, line):
|
|
self.flag_command(self.session.set_verbosity, line)
|
|
def help_verbose(self):
|
|
- print "Usage: verbose {on|off|enable|disable|yes|no}"
|
|
- print "Enables display of HTTP requests."
|
|
+ print("Usage: verbose {on|off|enable|disable|yes|no}")
|
|
+ print("Enables display of HTTP requests.")
|
|
|
|
def do_host(self, line):
|
|
self.session.set_host_name(line)
|
|
return 0
|
|
def help_host(self):
|
|
- print "Usage: host <hostname>"
|
|
- print "Sets the Host field to be queried by the ISP."
|
|
+ print("Usage: host <hostname>")
|
|
+ print("Sets the Host field to be queried by the ISP.")
|
|
|
|
def do_domain(self, line):
|
|
- print "Usage: host <domainname>"
|
|
+ print("Usage: host <domainname>")
|
|
self.session.set_domain_name(line)
|
|
return 0
|
|
def help_domain(self):
|
|
- print "Sets the Domain field to be queried by the ISP."
|
|
+ print("Sets the Domain field to be queried by the ISP.")
|
|
|
|
def do_lan_address(self, line):
|
|
self.session.set_LAN_IP(line)
|
|
return 0
|
|
def help_lan_address(self):
|
|
- print "Usage: lan_address <ip-address>"
|
|
- print "Sets the LAN IP address."
|
|
+ print("Usage: lan_address <ip-address>")
|
|
+ print("Sets the LAN IP address.")
|
|
|
|
def do_lan_netmask(self, line):
|
|
self.session.set_LAN_netmask(line)
|
|
return 0
|
|
def help_lan_netmask(self):
|
|
- print "Usage: lan_netmask <ip-mask>"
|
|
- print "Sets the LAN subnetwork mask."
|
|
+ print("Usage: lan_netmask <ip-mask>")
|
|
+ print("Sets the LAN subnetwork mask.")
|
|
|
|
def do_wireless(self, line):
|
|
self.flag_command(self.session.set_wireless, line)
|
|
return 0
|
|
def help_wireless(self):
|
|
- print "Usage: wireless {on|off|enable|disable|yes|no}"
|
|
- print "Switch to enable or disable wireless features."
|
|
+ print("Usage: wireless {on|off|enable|disable|yes|no}")
|
|
+ print("Switch to enable or disable wireless features.")
|
|
|
|
def do_ssid(self, line):
|
|
self.session.set_SSID(line)
|
|
return 0
|
|
def help_ssid(self):
|
|
- print "Usage: ssid <string>"
|
|
- print "Sets the SSID used to control wireless access."
|
|
+ print("Usage: ssid <string>")
|
|
+ print("Sets the SSID used to control wireless access.")
|
|
|
|
def do_ssid_broadcast(self, line):
|
|
self.flag_command(self.session.set_SSID_broadcast, line)
|
|
return 0
|
|
def help_ssid_broadcast(self):
|
|
- print "Usage: ssid_broadcast {on|off|enable|disable|yes|no}"
|
|
- print "Switch to enable or disable SSID broadcast."
|
|
+ print("Usage: ssid_broadcast {on|off|enable|disable|yes|no}")
|
|
+ print("Switch to enable or disable SSID broadcast.")
|
|
|
|
def do_channel(self, line):
|
|
self.session.set_channel(line)
|
|
return 0
|
|
def help_channel(self):
|
|
- print "Usage: channel <number>"
|
|
- print "Sets the wireless channel."
|
|
+ print("Usage: channel <number>")
|
|
+ print("Sets the wireless channel.")
|
|
|
|
def do_wep(self, line):
|
|
self.flag_command(self.session.set_WEP, line)
|
|
return 0
|
|
def help_wep(self):
|
|
- print "Usage: wep {on|off|enable|disable|yes|no}"
|
|
- print "Switch to enable or disable WEP security."
|
|
+ print("Usage: wep {on|off|enable|disable|yes|no}")
|
|
+ print("Switch to enable or disable WEP security.")
|
|
|
|
def do_wan_type(self, line):
|
|
try:
|
|
@@ -345,29 +345,29 @@ if __name__ == "__main__":
|
|
print >>sys.stderr, "linksys: unknown connection type."
|
|
return 0
|
|
def help_wan_type(self):
|
|
- print "Usage: wan_type {auto|static|ppoe|ras|pptp|heartbeat}"
|
|
- print "Set the WAN connection type."
|
|
+ print("Usage: wan_type {auto|static|ppoe|ras|pptp|heartbeat}")
|
|
+ print("Set the WAN connection type.")
|
|
|
|
def do_wan_address(self, line):
|
|
self.session.set_WAN_IP(line)
|
|
return 0
|
|
def help_wan_address(self):
|
|
- print "Usage: wan_address <ip-address>"
|
|
- print "Sets the WAN IP address."
|
|
+ print("Usage: wan_address <ip-address>")
|
|
+ print("Sets the WAN IP address.")
|
|
|
|
def do_wan_netmask(self, line):
|
|
self.session.set_WAN_netmask(line)
|
|
return 0
|
|
def help_wan_netmask(self):
|
|
- print "Usage: wan_netmask <ip-mask>"
|
|
- print "Sets the WAN subnetwork mask."
|
|
+ print("Usage: wan_netmask <ip-mask>")
|
|
+ print("Sets the WAN subnetwork mask.")
|
|
|
|
def do_wan_gateway(self, line):
|
|
self.session.set_WAN_gateway(line)
|
|
return 0
|
|
def help_wan_gateway(self):
|
|
- print "Usage: wan_gateway <ip-address>"
|
|
- print "Sets the LAN subnetwork mask."
|
|
+ print("Usage: wan_gateway <ip-address>")
|
|
+ print("Sets the LAN subnetwork mask.")
|
|
|
|
def do_dns(self, line):
|
|
(index, address) = line.split()
|
|
@@ -377,52 +377,52 @@ if __name__ == "__main__":
|
|
print >>sys.stderr, "linksys: server index out of bounds."
|
|
return 0
|
|
def help_dns(self):
|
|
- print "Usage: dns {1|2|3} <ip-mask>"
|
|
- print "Sets a primary, secondary, or tertiary DNS server address."
|
|
+ print("Usage: dns {1|2|3} <ip-mask>")
|
|
+ print("Sets a primary, secondary, or tertiary DNS server address.")
|
|
|
|
def do_password(self, line):
|
|
self.session.set_password(line)
|
|
return 0
|
|
def help_password(self):
|
|
- print "Usage: password <string>"
|
|
- print "Sets the router password."
|
|
+ print("Usage: password <string>")
|
|
+ print("Sets the router password.")
|
|
|
|
def do_upnp(self, line):
|
|
self.flag_command(self.session.set_UPnP, line)
|
|
return 0
|
|
def help_upnp(self):
|
|
- print "Usage: upnp {on|off|enable|disable|yes|no}"
|
|
- print "Switch to enable or disable Universal Plug and Play."
|
|
+ print("Usage: upnp {on|off|enable|disable|yes|no}")
|
|
+ print("Switch to enable or disable Universal Plug and Play.")
|
|
|
|
def do_reset(self, line):
|
|
self.session.reset()
|
|
def help_reset(self):
|
|
- print "Usage: reset"
|
|
- print "Reset Linksys settings to factory defaults."
|
|
+ print("Usage: reset")
|
|
+ print("Reset Linksys settings to factory defaults.")
|
|
|
|
def do_dhcp(self, line):
|
|
self.flag_command(self.session.set_DHCP, line)
|
|
def help_dhcp(self):
|
|
- print "Usage: dhcp {on|off|enable|disable|yes|no}"
|
|
- print "Switch to enable or disable DHCP features."
|
|
+ print("Usage: dhcp {on|off|enable|disable|yes|no}")
|
|
+ print("Switch to enable or disable DHCP features.")
|
|
|
|
def do_dhcp_start(self, line):
|
|
self.session.set_DHCP_starting_IP(line)
|
|
def help_dhcp_start(self):
|
|
- print "Usage: dhcp_start <number>"
|
|
- print "Set the start address of the DHCP pool."
|
|
+ print("Usage: dhcp_start <number>")
|
|
+ print("Set the start address of the DHCP pool.")
|
|
|
|
def do_dhcp_users(self, line):
|
|
self.session.set_DHCP_users(line)
|
|
def help_dhcp_users(self):
|
|
- print "Usage: dhcp_users <number>"
|
|
- print "Set number of address slots to allocate in the DHCP pool."
|
|
+ print("Usage: dhcp_users <number>")
|
|
+ print("Set number of address slots to allocate in the DHCP pool.")
|
|
|
|
def do_dhcp_lease(self, line):
|
|
self.session.set_DHCP_lease(line)
|
|
def help_dhcp_lease(self):
|
|
- print "Usage: dhcp_lease <number>"
|
|
- print "Set number of address slots to allocate in the DHCP pool."
|
|
+ print("Usage: dhcp_lease <number>")
|
|
+ print("Set number of address slots to allocate in the DHCP pool.")
|
|
|
|
def do_dhcp_dns(self, line):
|
|
(index, address) = line.split()
|
|
@@ -432,46 +432,46 @@ if __name__ == "__main__":
|
|
print >>sys.stderr, "linksys: server index out of bounds."
|
|
return 0
|
|
def help_dhcp_dns(self):
|
|
- print "Usage: dhcp_dns {1|2|3} <ip-mask>"
|
|
- print "Sets primary, secondary, or tertiary DNS server address."
|
|
+ print("Usage: dhcp_dns {1|2|3} <ip-mask>")
|
|
+ print("Sets primary, secondary, or tertiary DNS server address.")
|
|
|
|
def do_logging(self, line):
|
|
self.flag_command(self.session.set_logging, line)
|
|
def help_logging(self):
|
|
- print "Usage: logging {on|off|enable|disable|yes|no}"
|
|
- print "Switch to enable or disable session logging."
|
|
+ print("Usage: logging {on|off|enable|disable|yes|no}")
|
|
+ print("Switch to enable or disable session logging.")
|
|
|
|
def do_log_address(self, line):
|
|
self.session.set_Log_address(line)
|
|
def help_log_address(self):
|
|
- print "Usage: log_address <number>"
|
|
- print "Set the last quad of the address to which to log."
|
|
+ print("Usage: log_address <number>")
|
|
+ print("Set the last quad of the address to which to log.")
|
|
|
|
def do_configure(self, line):
|
|
self.session.configure()
|
|
return 0
|
|
def help_configure(self):
|
|
- print "Usage: configure"
|
|
- print "Writes the configuration to the Linksys."
|
|
+ print("Usage: configure")
|
|
+ print("Writes the configuration to the Linksys.")
|
|
|
|
def do_cache(self, line):
|
|
- print self.session.pagecache
|
|
+ print(self.session.pagecache)
|
|
def help_cache(self):
|
|
- print "Usage: cache"
|
|
- print "Display the page cache."
|
|
+ print("Usage: cache")
|
|
+ print("Display the page cache.")
|
|
|
|
def do_quit(self, line):
|
|
return 1
|
|
def help_quit(self, line):
|
|
- print "The quit command ends your linksys session without"
|
|
- print "writing configuration changes to the Linksys."
|
|
+ print("The quit command ends your linksys session without")
|
|
+ print("writing configuration changes to the Linksys.")
|
|
def do_EOF(self, line):
|
|
- print ""
|
|
+ print("")
|
|
self.session.configure()
|
|
return 1
|
|
def help_EOF(self):
|
|
- print "The EOF command writes the configuration to the linksys"
|
|
- print "and ends your session."
|
|
+ print("The EOF command writes the configuration to the linksys")
|
|
+ print("and ends your session.")
|
|
|
|
def default(self, line):
|
|
"""Pass the command through to be executed by the shell."""
|
|
@@ -479,11 +479,11 @@ if __name__ == "__main__":
|
|
return 0
|
|
|
|
def help_help(self):
|
|
- print "On-line help is available through this command."
|
|
- print "? is a convenience alias for help."
|
|
+ print("On-line help is available through this command.")
|
|
+ print("? is a convenience alias for help.")
|
|
|
|
def help_introduction(self):
|
|
- print """\
|
|
+ print("""\
|
|
|
|
This program supports changing the settings on Linksys blue-box routers. This
|
|
capability may come in handy when they freeze up and have to be reset. Though
|
|
@@ -506,16 +506,16 @@ will be shipped to the Linksys at the end of session (e.g. when the program
|
|
running in batch mode encounters end-of-file or you type a control-D). If you
|
|
end the session with `quit', pending changes will be discarded.
|
|
|
|
-For more help, read the topics 'wan', 'lan', and 'wireless'."""
|
|
+For more help, read the topics 'wan', 'lan', and 'wireless'.""")
|
|
|
|
def help_lan(self):
|
|
- print """\
|
|
+ print("""\
|
|
The `lan_address' and `lan_netmask' commands let you set the IP location of
|
|
the Linksys on your LAN, or inside. Normally you'll want to leave these
|
|
-untouched."""
|
|
+untouched.""")
|
|
|
|
def help_wan(self):
|
|
- print """\
|
|
+ print("""\
|
|
The WAN commands become significant if you are using the BEFSR41 or any of
|
|
the other Linksys boxes designed as DSL or cable-modem gateways. You will
|
|
need to use `wan_type' to declare how you expect to get your address.
|
|
@@ -527,22 +527,22 @@ need to use the `dns' command to declare which remote servers your DNS
|
|
requests should be forwarded to.
|
|
|
|
Some ISPs may require you to set host and domain for use with dynamic-address
|
|
-allocation."""
|
|
+allocation.""")
|
|
|
|
def help_wireless(self):
|
|
- print """\
|
|
+ print("""\
|
|
The channel, ssid, ssid_broadcast, wep, and wireless commands control
|
|
-wireless routing."""
|
|
+wireless routing.""")
|
|
|
|
def help_switches(self):
|
|
- print "Switches may be turned on with 'on', 'enable', or 'yes'."
|
|
- print "Switches may be turned off with 'off', 'disable', or 'no'."
|
|
- print "Switch commands include: wireless, ssid_broadcast."
|
|
+ print("Switches may be turned on with 'on', 'enable', or 'yes'.")
|
|
+ print("Switches may be turned off with 'off', 'disable', or 'no'.")
|
|
+ print("Switch commands include: wireless, ssid_broadcast.")
|
|
|
|
def help_addresses(self):
|
|
- print "An address argument must be a valid IP address;"
|
|
- print "four decimal numbers separated by dots, each "
|
|
- print "between 0 and 255."
|
|
+ print("An address argument must be a valid IP address;")
|
|
+ print("four decimal numbers separated by dots, each ")
|
|
+ print("between 0 and 255.")
|
|
|
|
def emptyline(self):
|
|
pass
|
|
diff --git a/examples/retriever-multi.py b/examples/retriever-multi.py
|
|
index 1a941be..ad4cebd 100644
|
|
--- a/examples/retriever-multi.py
|
|
+++ b/examples/retriever-multi.py
|
|
@@ -31,7 +31,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 +50,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
|
|
@@ -95,13 +95,13 @@ while num_processed < num_urls:
|
|
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:
|
|
diff --git a/examples/retriever.py b/examples/retriever.py
|
|
index 2c91d07..be1b6ea 100644
|
|
--- a/examples/retriever.py
|
|
+++ b/examples/retriever.py
|
|
@@ -31,7 +31,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 +50,8 @@ assert queue.queue, "no URLs given"
|
|
num_urls = len(queue.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 -----")
|
|
|
|
|
|
class WorkerThread(threading.Thread):
|
|
diff --git a/examples/sfquery.py b/examples/sfquery.py
|
|
index 741feb0..16aa9d4 100644
|
|
--- a/examples/sfquery.py
|
|
+++ b/examples/sfquery.py
|
|
@@ -40,7 +40,7 @@ if __name__ == "__main__":
|
|
name, account, password = auth
|
|
except:
|
|
if len(sys.argv) < 4:
|
|
- print "Usage: %s <project id> <username> <password>" % sys.argv[0]
|
|
+ print("Usage: %s <project id> <username> <password>" % sys.argv[0])
|
|
raise SystemExit
|
|
name = sys.argv[2]
|
|
password = sys.argv[3]
|
|
diff --git a/examples/xmlrpc_curl.py b/examples/xmlrpc_curl.py
|
|
index ec0df50..a9a7d9e 100644
|
|
--- a/examples/xmlrpc_curl.py
|
|
+++ b/examples/xmlrpc_curl.py
|
|
@@ -55,8 +55,8 @@ if __name__ == "__main__":
|
|
## Test
|
|
server = xmlrpclib.ServerProxy("http://betty.userland.com",
|
|
transport=CURLTransport())
|
|
- print server
|
|
+ print(server)
|
|
try:
|
|
- print server.examples.getStateName(41)
|
|
+ print(server.examples.getStateName(41))
|
|
except xmlrpclib.Error, v:
|
|
- print "ERROR", v
|
|
+ print("ERROR", v)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bb811ad5b2d2819d502c84c735b7efec84d4d557 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 28 Feb 2013 00:30:00 -0500
|
|
Subject: [PATCH 110/149] Python 3 compatibility: printing to stderr (linksys example)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
examples/linksys.py | 14 +++++++++-----
|
|
1 files changed, 9 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/examples/linksys.py b/examples/linksys.py
|
|
index 24cb2a9..f66ff0d 100755
|
|
--- a/examples/linksys.py
|
|
+++ b/examples/linksys.py
|
|
@@ -34,6 +34,10 @@
|
|
|
|
import sys, re, copy, curl, exceptions
|
|
|
|
+def print_stderr(arg):
|
|
+ sys.stderr.write(arg)
|
|
+ sys.stderr.write("\n")
|
|
+
|
|
class LinksysError(exceptions.Exception):
|
|
def __init__(self, *args):
|
|
self.args = args
|
|
@@ -202,7 +206,7 @@ class LinksysSession:
|
|
for (page, field, value) in self.actions:
|
|
self.cache_load(page)
|
|
if self.pagecache[page].find(field) == -1:
|
|
- print >>sys.stderr, "linksys: field %s not found where expected in page %s!" % (field, os.path.join(self.host, page))
|
|
+ print_stderr("linksys: field %s not found where expected in page %s!" % (field, os.path.join(self.host, page)))
|
|
continue
|
|
else:
|
|
fields.append((field, value))
|
|
@@ -236,7 +240,7 @@ if __name__ == "__main__":
|
|
elif line.strip() in ("off", "disable", "no"):
|
|
func(False)
|
|
else:
|
|
- print >>sys.stderr, "linksys: unknown switch value"
|
|
+ print_stderr("linksys: unknown switch value")
|
|
return 0
|
|
|
|
def do_connect(self, line):
|
|
@@ -342,7 +346,7 @@ if __name__ == "__main__":
|
|
type=eval("LinksysSession.WAN_CONNECT_"+line.strip().upper())
|
|
self.session.set_connection_type(type)
|
|
except ValueError:
|
|
- print >>sys.stderr, "linksys: unknown connection type."
|
|
+ print_stderr("linksys: unknown connection type.")
|
|
return 0
|
|
def help_wan_type(self):
|
|
print("Usage: wan_type {auto|static|ppoe|ras|pptp|heartbeat}")
|
|
@@ -374,7 +378,7 @@ if __name__ == "__main__":
|
|
if index in ("1", "2", "3"):
|
|
self.session.set_DNS_server(eval(index), address)
|
|
else:
|
|
- print >>sys.stderr, "linksys: server index out of bounds."
|
|
+ print_stderr("linksys: server index out of bounds.")
|
|
return 0
|
|
def help_dns(self):
|
|
print("Usage: dns {1|2|3} <ip-mask>")
|
|
@@ -429,7 +433,7 @@ if __name__ == "__main__":
|
|
if index in ("1", "2", "3"):
|
|
self.session.set_DHCP_DNS_server(eval(index), address)
|
|
else:
|
|
- print >>sys.stderr, "linksys: server index out of bounds."
|
|
+ print_stderr("linksys: server index out of bounds.")
|
|
return 0
|
|
def help_dhcp_dns(self):
|
|
print("Usage: dhcp_dns {1|2|3} <ip-mask>")
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2ea28565bcf16bb2e792467650012081e2268cf1 Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Mon, 8 Apr 2013 14:25:26 +0200
|
|
Subject: [PATCH 111/149] allow to unset a previously set RANGE value
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
... and add the unset_range_test.py unit test exercising it
|
|
|
|
Reported by: Zdeněk Pavlas
|
|
Bug: https://bugzilla.redhat.com/928370
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 1 +
|
|
tests/unset_range_test.py | 39 +++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 40 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/unset_range_test.py
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index a30c339..bd28b81 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -1561,6 +1561,7 @@ util_curl_unsetopt(CurlObject *self, int option)
|
|
case CURLOPT_RANDOM_FILE:
|
|
case CURLOPT_SSL_CIPHER_LIST:
|
|
case CURLOPT_USERPWD:
|
|
+ case CURLOPT_RANGE:
|
|
SETOPT((char *) 0);
|
|
break;
|
|
|
|
diff --git a/tests/unset_range_test.py b/tests/unset_range_test.py
|
|
new file mode 100644
|
|
index 0000000..4400851
|
|
--- /dev/null
|
|
+++ b/tests/unset_range_test.py
|
|
@@ -0,0 +1,39 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import os.path
|
|
+import pycurl
|
|
+import sys
|
|
+import unittest
|
|
+
|
|
+class UnsetRangeTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_unset_range(self):
|
|
+ def write_cb(data):
|
|
+ self.read += len(data)
|
|
+ return None
|
|
+
|
|
+ # download bytes 0-9 of the script itself through the file:// protocol
|
|
+ self.read = 0
|
|
+ self.curl.setopt(pycurl.URL, 'file://' + os.path.abspath(sys.argv[0]))
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, write_cb)
|
|
+ self.curl.setopt(pycurl.RANGE, '0-9')
|
|
+ self.curl.perform()
|
|
+ assert 10 == self.read
|
|
+
|
|
+ # the RANGE setting should be preserved from the previous transfer
|
|
+ self.read = 0
|
|
+ self.curl.perform()
|
|
+ assert 10 == self.read
|
|
+
|
|
+ # drop the RANGE setting using unsetopt() and download entire script
|
|
+ self.read = 0
|
|
+ self.curl.unsetopt(pycurl.RANGE)
|
|
+ self.curl.perform()
|
|
+ assert 10 < self.read
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 576e87580356497b601ec16a9a794db959d43f0e Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Mon, 8 Apr 2013 14:31:30 +0200
|
|
Subject: [PATCH 112/149] allow to use setopt(..., None) as unsetopt()
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
... and extend the unset_range_test.py unit test to exercise it
|
|
|
|
Reported by: Zdeněk Pavlas
|
|
Bug: https://bugzilla.redhat.com/928370
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 4 +---
|
|
tests/unset_range_test.py | 12 ++++++++++++
|
|
2 files changed, 13 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index bd28b81..619ca20 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -1631,12 +1631,10 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
if (option % 10000 >= OPTIONS_SIZE)
|
|
goto error;
|
|
|
|
-#if 0 /* XXX - should we ??? */
|
|
- /* Handle the case of None */
|
|
+ /* Handle the case of None as the call of unsetopt() */
|
|
if (obj == Py_None) {
|
|
return util_curl_unsetopt(self, option);
|
|
}
|
|
-#endif
|
|
|
|
/* Handle the case of string arguments */
|
|
if (PyString_Check(obj)) {
|
|
diff --git a/tests/unset_range_test.py b/tests/unset_range_test.py
|
|
index 4400851..10ee801 100644
|
|
--- a/tests/unset_range_test.py
|
|
+++ b/tests/unset_range_test.py
|
|
@@ -37,3 +37,15 @@ class UnsetRangeTest(unittest.TestCase):
|
|
self.curl.unsetopt(pycurl.RANGE)
|
|
self.curl.perform()
|
|
assert 10 < self.read
|
|
+
|
|
+ # now set the RANGE again and check that pycurl takes it into account
|
|
+ self.read = 0
|
|
+ self.curl.setopt(pycurl.RANGE, '0-9')
|
|
+ self.curl.perform()
|
|
+ assert 10 == self.read
|
|
+
|
|
+ # now drop the RANGE setting using setopt(..., None)
|
|
+ self.read = 0
|
|
+ self.curl.setopt(pycurl.RANGE, None)
|
|
+ self.curl.perform()
|
|
+ assert 10 < self.read
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 5c27a721fc3aaeaeddabb394ae6c9502391bdea6 Mon Sep 17 00:00:00 2001
|
|
From: Zdenek Pavlas <zpavlas@redhat.com>
|
|
Date: Wed, 13 Mar 2013 16:55:58 +0100
|
|
Subject: [PATCH 113/149] add the GLOBAL_ACK_EINTR constant to the list of exported symbols
|
|
|
|
... if built against a new enough version of libcurl
|
|
|
|
Bug: https://bugzilla.redhat.com/920589
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 19 +++++++++++++++----
|
|
1 files changed, 15 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 619ca20..9950e00 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -3210,6 +3210,16 @@ static PyTypeObject CurlMulti_Type = {
|
|
*/
|
|
};
|
|
|
|
+static int
|
|
+are_global_init_flags_valid(int flags)
|
|
+{
|
|
+#ifdef CURL_GLOBAL_ACK_EINTR
|
|
+ /* CURL_GLOBAL_ACK_EINTR was introduced in libcurl-7.30.0 */
|
|
+ return !(flags & ~(CURL_GLOBAL_ALL | CURL_GLOBAL_ACK_EINTR));
|
|
+#else
|
|
+ return !(flags & ~(CURL_GLOBAL_ALL));
|
|
+#endif
|
|
+}
|
|
|
|
/*************************************************************************
|
|
// module level
|
|
@@ -3227,10 +3237,7 @@ do_global_init(PyObject *dummy, PyObject *args)
|
|
return NULL;
|
|
}
|
|
|
|
- if (!(option == CURL_GLOBAL_SSL ||
|
|
- option == CURL_GLOBAL_WIN32 ||
|
|
- option == CURL_GLOBAL_ALL ||
|
|
- option == CURL_GLOBAL_NOTHING)) {
|
|
+ if (!are_global_init_flags_valid(option)) {
|
|
PyErr_SetString(PyExc_ValueError, "invalid option to global_init");
|
|
return NULL;
|
|
}
|
|
@@ -3866,6 +3873,10 @@ initpycurl(void)
|
|
insint(d, "GLOBAL_ALL", CURL_GLOBAL_ALL);
|
|
insint(d, "GLOBAL_NOTHING", CURL_GLOBAL_NOTHING);
|
|
insint(d, "GLOBAL_DEFAULT", CURL_GLOBAL_DEFAULT);
|
|
+#ifdef CURL_GLOBAL_ACK_EINTR
|
|
+ /* CURL_GLOBAL_ACK_EINTR was introduced in libcurl-7.30.0 */
|
|
+ insint(d, "GLOBAL_ACK_EINTR", CURL_GLOBAL_ACK_EINTR);
|
|
+#endif
|
|
|
|
|
|
/* constants for curl_multi_socket interface */
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 5a165baaa2b275293c1e045d8c0023d55bd0cbfc Mon Sep 17 00:00:00 2001
|
|
From: Kamil Dudka <kdudka@redhat.com>
|
|
Date: Wed, 3 Apr 2013 15:06:32 +0200
|
|
Subject: [PATCH 114/149] tests/global_init_ack_eintr.py: test GLOBAL_ACK_EINTR
|
|
|
|
... if we have a new enough version of libcurl
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/global_init_ack_eintr.py | 22 ++++++++++++++++++++++
|
|
1 files changed, 22 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/global_init_ack_eintr.py
|
|
|
|
diff --git a/tests/global_init_ack_eintr.py b/tests/global_init_ack_eintr.py
|
|
new file mode 100644
|
|
index 0000000..429fc3f
|
|
--- /dev/null
|
|
+++ b/tests/global_init_ack_eintr.py
|
|
@@ -0,0 +1,22 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+
|
|
+from . import util
|
|
+
|
|
+class GlobalInitAckEintrTest(unittest.TestCase):
|
|
+ def test_global_init_default(self):
|
|
+ # initialize libcurl with DEFAULT flags
|
|
+ pycurl.global_init(pycurl.GLOBAL_DEFAULT)
|
|
+ pycurl.global_cleanup()
|
|
+
|
|
+ def test_global_init_ack_eintr(self):
|
|
+ # the GLOBAL_ACK_EINTR flag was introduced in libcurl-7.30, but can also
|
|
+ # be backported for older versions of libcurl at the distribution level
|
|
+ if not util.pycurl_version_less_than(7, 30) or hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
+ # initialize libcurl with the GLOBAL_ACK_EINTR flag
|
|
+ pycurl.global_init(pycurl.GLOBAL_ACK_EINTR)
|
|
+ pycurl.global_cleanup()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 788e012e64250cfb473d201a836e1a92c7772154 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 9 Apr 2013 18:52:41 -0400
|
|
Subject: [PATCH 115/149] Add a test for bogus init flags and fix test name
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/global_init_ack_eintr.py | 22 ----------------------
|
|
tests/global_init_test.py | 28 ++++++++++++++++++++++++++++
|
|
2 files changed, 28 insertions(+), 22 deletions(-)
|
|
delete mode 100644 tests/global_init_ack_eintr.py
|
|
create mode 100644 tests/global_init_test.py
|
|
|
|
diff --git a/tests/global_init_ack_eintr.py b/tests/global_init_ack_eintr.py
|
|
deleted file mode 100644
|
|
index 429fc3f..0000000
|
|
--- a/tests/global_init_ack_eintr.py
|
|
+++ /dev/null
|
|
@@ -1,22 +0,0 @@
|
|
-#! /usr/bin/env python
|
|
-# -*- coding: iso-8859-1 -*-
|
|
-# vi:ts=4:et
|
|
-
|
|
-import pycurl
|
|
-import unittest
|
|
-
|
|
-from . import util
|
|
-
|
|
-class GlobalInitAckEintrTest(unittest.TestCase):
|
|
- def test_global_init_default(self):
|
|
- # initialize libcurl with DEFAULT flags
|
|
- pycurl.global_init(pycurl.GLOBAL_DEFAULT)
|
|
- pycurl.global_cleanup()
|
|
-
|
|
- def test_global_init_ack_eintr(self):
|
|
- # the GLOBAL_ACK_EINTR flag was introduced in libcurl-7.30, but can also
|
|
- # be backported for older versions of libcurl at the distribution level
|
|
- if not util.pycurl_version_less_than(7, 30) or hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
- # initialize libcurl with the GLOBAL_ACK_EINTR flag
|
|
- pycurl.global_init(pycurl.GLOBAL_ACK_EINTR)
|
|
- pycurl.global_cleanup()
|
|
diff --git a/tests/global_init_test.py b/tests/global_init_test.py
|
|
new file mode 100644
|
|
index 0000000..b76254b
|
|
--- /dev/null
|
|
+++ b/tests/global_init_test.py
|
|
@@ -0,0 +1,28 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import nose.tools
|
|
+
|
|
+from . import util
|
|
+
|
|
+class GlobalInitTest(unittest.TestCase):
|
|
+ def test_global_init_default(self):
|
|
+ # initialize libcurl with DEFAULT flags
|
|
+ pycurl.global_init(pycurl.GLOBAL_DEFAULT)
|
|
+ pycurl.global_cleanup()
|
|
+
|
|
+ def test_global_init_ack_eintr(self):
|
|
+ # the GLOBAL_ACK_EINTR flag was introduced in libcurl-7.30, but can also
|
|
+ # be backported for older versions of libcurl at the distribution level
|
|
+ if not util.pycurl_version_less_than(7, 30) or hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
+ # initialize libcurl with the GLOBAL_ACK_EINTR flag
|
|
+ pycurl.global_init(pycurl.GLOBAL_ACK_EINTR)
|
|
+ pycurl.global_cleanup()
|
|
+
|
|
+ @nose.tools.raises(ValueError)
|
|
+ def test_global_init_bogus(self):
|
|
+ # initialize libcurl with bogus flags
|
|
+ pycurl.global_init(0xffff)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 91992e2ef3664d68c8e98269b78911b929ad991a Mon Sep 17 00:00:00 2001
|
|
From: anonymous <anonymous@users.sourceforge.net>
|
|
Date: Tue, 26 Feb 2013 16:32:20 -0500
|
|
Subject: [PATCH 116/149] Python 3 support.
|
|
|
|
http://sourceforge.net/tracker/?func=detail&aid=2917775&group_id=28236&atid=392779
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
setup.py | 18 +++++++++---------
|
|
1 files changed, 9 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/setup.py b/setup.py
|
|
index 725007c..e0d0379 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
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 6f6649b79ea66493e878eda3e3cfd87cba18a02f Mon Sep 17 00:00:00 2001
|
|
From: decitre <decitre@users.sourceforge.net>
|
|
Date: Tue, 26 Feb 2013 16:36:32 -0500
|
|
Subject: [PATCH 117/149] Corrected Python 3 support.
|
|
|
|
http://sourceforge.net/tracker/?func=detail&aid=3188495&group_id=28236&atid=392779
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
setup.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/setup.py b/setup.py
|
|
index e0d0379..385facb 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -106,7 +106,7 @@ else:
|
|
stdout=subprocess.PIPE)
|
|
(stdout, stderr) = p.communicate()
|
|
if p.wait() == 0:
|
|
- optbuf += stdout
|
|
+ optbuf += stdout.decode()
|
|
if optbuf == "":
|
|
raise Exception("Neither of curl-config --libs or --static-libs" +
|
|
"produced output")
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d256095c74857a87fa7e3c9dbb0df58cdeded17f Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 28 Feb 2013 00:14:03 -0500
|
|
Subject: [PATCH 118/149] Python 3 compatibility: StringIO (src)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
python/curl/__init__.py | 5 ++++-
|
|
1 files changed, 4 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/python/curl/__init__.py b/python/curl/__init__.py
|
|
index 5617262..3ab019f 100644
|
|
--- a/python/curl/__init__.py
|
|
+++ b/python/curl/__init__.py
|
|
@@ -10,7 +10,10 @@ import os, sys, urllib, exceptions, mimetools, pycurl
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
- from StringIO import StringIO
|
|
+ try:
|
|
+ from StringIO import StringIO
|
|
+ except ImportError:
|
|
+ from io import StringIO
|
|
|
|
try:
|
|
import signal
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 04ebd364f9b027e0bbdaeecfca02493244efcfbd Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 28 Feb 2013 00:11:58 -0500
|
|
Subject: [PATCH 119/149] Python 3 compatibility: StringIO (examples)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
examples/xmlrpc_curl.py | 5 ++++-
|
|
1 files changed, 4 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/examples/xmlrpc_curl.py b/examples/xmlrpc_curl.py
|
|
index a9a7d9e..bb6799e 100644
|
|
--- a/examples/xmlrpc_curl.py
|
|
+++ b/examples/xmlrpc_curl.py
|
|
@@ -14,7 +14,10 @@ except ImportError:
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
- from StringIO import StringIO
|
|
+ try:
|
|
+ from StringIO import StringIO
|
|
+ except ImportError:
|
|
+ from io import StringIO
|
|
import xmlrpclib, pycurl
|
|
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 936cceff39402efa5b91b2ff4d4d36c04c1675c8 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 28 Feb 2013 00:23:29 -0500
|
|
Subject: [PATCH 120/149] Python 3 compatibility: xmlrpclib
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
examples/tests/test_xmlrpc.py | 5 ++++-
|
|
examples/xmlrpc_curl.py | 6 +++++-
|
|
2 files changed, 9 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/examples/tests/test_xmlrpc.py b/examples/tests/test_xmlrpc.py
|
|
index 3a5469a..d64794e 100644
|
|
--- a/examples/tests/test_xmlrpc.py
|
|
+++ b/examples/tests/test_xmlrpc.py
|
|
@@ -4,7 +4,10 @@
|
|
# $Id$
|
|
|
|
## XML-RPC lib included in python2.2
|
|
-import xmlrpclib
|
|
+try:
|
|
+ import xmlrpclib
|
|
+except ImportError:
|
|
+ import xmlrpc.client as xmlrpclib
|
|
import pycurl
|
|
|
|
# Header fields passed in request
|
|
diff --git a/examples/xmlrpc_curl.py b/examples/xmlrpc_curl.py
|
|
index bb6799e..21418b5 100644
|
|
--- a/examples/xmlrpc_curl.py
|
|
+++ b/examples/xmlrpc_curl.py
|
|
@@ -18,7 +18,11 @@ except ImportError:
|
|
from StringIO import StringIO
|
|
except ImportError:
|
|
from io import StringIO
|
|
-import xmlrpclib, pycurl
|
|
+try:
|
|
+ import xmlrpclib
|
|
+except ImportError:
|
|
+ import xmlrpc.client as xmlrpclib
|
|
+import pycurl
|
|
|
|
|
|
class CURLTransport(xmlrpclib.Transport):
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 00ce4e4176540bc899713bcd2c364ad8d3887a8b Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 28 Feb 2013 00:34:01 -0500
|
|
Subject: [PATCH 121/149] Python 3 compatibility: urllib (src)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
python/curl/__init__.py | 10 +++++++---
|
|
1 files changed, 7 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/python/curl/__init__.py b/python/curl/__init__.py
|
|
index 3ab019f..fd179fc 100644
|
|
--- a/python/curl/__init__.py
|
|
+++ b/python/curl/__init__.py
|
|
@@ -6,7 +6,11 @@
|
|
#
|
|
# By Eric S. Raymond, April 2003.
|
|
|
|
-import os, sys, urllib, exceptions, mimetools, pycurl
|
|
+import os, sys, exceptions, mimetools, pycurl
|
|
+try:
|
|
+ import urllib.parse as urllib_parse
|
|
+except ImportError:
|
|
+ import urllib as urllib_parse
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
@@ -86,14 +90,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 += "?" + urllib_parse.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, urllib_parse.urlencode(params))
|
|
return self.__request(cgi)
|
|
|
|
def body(self):
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 59cde00a2b6f4329d19579c3e8982d194c71eb66 Mon Sep 17 00:00:00 2001
|
|
From: Yuri Ushakov <yuri.ushakov@gmail.com>
|
|
Date: Thu, 18 Apr 2013 12:29:07 -0400
|
|
Subject: [PATCH 122/149] Correctly handle big timeout values
|
|
|
|
http://curl.haxx.se/mail/curlpython-2013-04/0000.html
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 9950e00..388595c 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -2567,7 +2567,7 @@ do_multi_timeout(CurlMultiObject *self)
|
|
}
|
|
|
|
/* Return number of millisecs until timeout */
|
|
- return Py_BuildValue("i", timeout);
|
|
+ return Py_BuildValue("l", timeout);
|
|
}
|
|
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 575f40dd24cea343980b0c628327d9a1008fa021 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 30 May 2013 13:55:35 -0400
|
|
Subject: [PATCH 123/149] Add support for CURLOPT_USERNAME / _PASSWORD
|
|
|
|
Original patch by Wim Lewis (https://sourceforge.net/u/wiml/profile/).
|
|
|
|
Original patch description:
|
|
|
|
This is a really trivial patch to add support for the CURLOPT_USERNAME and
|
|
CURLOPT_PASSWORD options (and their _PROXY equivalents), which affect
|
|
the same parts of libcurl's state that CURLOPT_USERPWD does but which
|
|
don't require you to combine the username and password into one string first.
|
|
(Libcurl just immediately parses it apart again anyway.)
|
|
|
|
I've tested against libcurl-7.21.0, and looked through the source for
|
|
libcurl 7.20.0 and 7.19.5 to verify that it looks like it should still do
|
|
the right things there (in particular that curl_easy_setopt(..., NULL)
|
|
does the reasonable thing with these options).
|
|
|
|
https://sourceforge.net/p/pycurl/patches/10/
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 31 +++++++++++++++++++++++++++++++
|
|
tests/curlopt_test.py | 18 ++++++++++++++++++
|
|
2 files changed, 49 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/curlopt_test.py
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 388595c..9c76609 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -61,6 +61,13 @@
|
|
# error "Need libcurl version 7.19.0 or greater to compile pycurl."
|
|
#endif
|
|
|
|
+#if LIBCURL_VERSION_MAJOR >= 8 || \
|
|
+ LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 20 || \
|
|
+ LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH >= 1
|
|
+#define HAVE_CURLOPT_USERNAME
|
|
+#define HAVE_CURLOPT_PROXYUSERNAME
|
|
+#endif
|
|
+
|
|
/* Python < 2.5 compat for Py_ssize_t */
|
|
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
|
|
typedef int Py_ssize_t;
|
|
@@ -1558,9 +1565,17 @@ util_curl_unsetopt(CurlObject *self, int option)
|
|
case CURLOPT_EGDSOCKET:
|
|
case CURLOPT_FTPPORT:
|
|
case CURLOPT_PROXYUSERPWD:
|
|
+#ifdef HAVE_CURLOPT_PROXYUSERNAME
|
|
+ case CURLOPT_PROXYUSERNAME:
|
|
+ case CURLOPT_PROXYPASSWORD:
|
|
+#endif
|
|
case CURLOPT_RANDOM_FILE:
|
|
case CURLOPT_SSL_CIPHER_LIST:
|
|
case CURLOPT_USERPWD:
|
|
+#ifdef HAVE_CURLOPT_USERNAME
|
|
+ case CURLOPT_USERNAME:
|
|
+ case CURLOPT_PASSWORD:
|
|
+#endif
|
|
case CURLOPT_RANGE:
|
|
SETOPT((char *) 0);
|
|
break;
|
|
@@ -1658,6 +1673,10 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
case CURLOPT_NETRC_FILE:
|
|
case CURLOPT_PROXY:
|
|
case CURLOPT_PROXYUSERPWD:
|
|
+#ifdef HAVE_CURLOPT_PROXYUSERNAME
|
|
+ case CURLOPT_PROXYUSERNAME:
|
|
+ case CURLOPT_PROXYPASSWORD:
|
|
+#endif
|
|
case CURLOPT_RANDOM_FILE:
|
|
case CURLOPT_RANGE:
|
|
case CURLOPT_REFERER:
|
|
@@ -1671,6 +1690,10 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
case CURLOPT_URL:
|
|
case CURLOPT_USERAGENT:
|
|
case CURLOPT_USERPWD:
|
|
+#ifdef HAVE_CURLOPT_USERNAME
|
|
+ case CURLOPT_USERNAME:
|
|
+ case CURLOPT_PASSWORD:
|
|
+#endif
|
|
case CURLOPT_FTP_ALTERNATIVE_TO_USER:
|
|
case CURLOPT_SSH_PUBLIC_KEYFILE:
|
|
case CURLOPT_SSH_PRIVATE_KEYFILE:
|
|
@@ -3654,7 +3677,15 @@ initpycurl(void)
|
|
insint_c(d, "PORT", CURLOPT_PORT);
|
|
insint_c(d, "PROXY", CURLOPT_PROXY);
|
|
insint_c(d, "USERPWD", CURLOPT_USERPWD);
|
|
+#ifdef HAVE_CURLOPT_USERNAME
|
|
+ insint_c(d, "USERNAME", CURLOPT_USERNAME);
|
|
+ insint_c(d, "PASSWORD", CURLOPT_PASSWORD);
|
|
+#endif
|
|
insint_c(d, "PROXYUSERPWD", CURLOPT_PROXYUSERPWD);
|
|
+#ifdef HAVE_CURLOPT_PROXYUSERNAME
|
|
+ insint_c(d, "PROXYUSERNAME", CURLOPT_PROXYUSERNAME);
|
|
+ insint_c(d, "PROXYPASSWORD", CURLOPT_PROXYPASSWORD);
|
|
+#endif
|
|
insint_c(d, "RANGE", CURLOPT_RANGE);
|
|
insint_c(d, "INFILE", CURLOPT_READDATA);
|
|
/* ERRORBUFFER is not supported */
|
|
diff --git a/tests/curlopt_test.py b/tests/curlopt_test.py
|
|
new file mode 100644
|
|
index 0000000..9392a39
|
|
--- /dev/null
|
|
+++ b/tests/curlopt_test.py
|
|
@@ -0,0 +1,18 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import nose.tools
|
|
+
|
|
+from . import util
|
|
+
|
|
+class CurloptTest(unittest.TestCase):
|
|
+ def test_username(self):
|
|
+ # CURLOPT_USERNAME was introduced in libcurl-7.19.1
|
|
+ if not util.pycurl_version_less_than(7, 19, 1):
|
|
+ assert hasattr(pycurl, 'USERNAME')
|
|
+ assert hasattr(pycurl, 'PASSWORD')
|
|
+ assert hasattr(pycurl, 'PROXYUSERNAME')
|
|
+ assert hasattr(pycurl, 'PROXYPASSWORD')
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From db2f9a10ef399f0a69b2e4a215fe44752f780b96 Mon Sep 17 00:00:00 2001
|
|
From: Adam Guthrie <therigu@users.sourceforge.net>
|
|
Date: Thu, 30 May 2013 14:10:44 -0400
|
|
Subject: [PATCH 124/149] Fixes invalid XHTML in documentation
|
|
|
|
doc/callbacks.html and doc/curlshareobject.html were not valid xhtml.
|
|
|
|
Thanks to Ivo Timmermans for the original report and patch to Ubuntu (LP: #364168)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
doc/callbacks.html | 2 +-
|
|
doc/curlshareobject.html | 3 ++-
|
|
2 files changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/doc/callbacks.html b/doc/callbacks.html
|
|
index b98e0a9..a117acc 100644
|
|
--- a/doc/callbacks.html
|
|
+++ b/doc/callbacks.html
|
|
@@ -120,7 +120,7 @@ VERBOSE option must be enabled for this callback to be invoked.</p>
|
|
</pre>
|
|
|
|
<h2>Other examples</h2>
|
|
-The pycurl distribution also contains a number of test scripts and
|
|
+<p>The pycurl distribution also contains a number of test scripts and
|
|
examples which show how to use the various callbacks in libcurl.
|
|
For instance, the file 'examples/file_upload.py' in the distribution contains
|
|
example code for using READFUNCTION, 'tests/test_cb.py' shows
|
|
diff --git a/doc/curlshareobject.html b/doc/curlshareobject.html
|
|
index c11cafb..2043e48 100644
|
|
--- a/doc/curlshareobject.html
|
|
+++ b/doc/curlshareobject.html
|
|
@@ -14,6 +14,7 @@
|
|
|
|
<p>CurlShare objects have the following methods:</p>
|
|
|
|
+<dl>
|
|
<dt><code>setopt(</code><em>option, value</em><code>)</code> -> <em>None</em></dt>
|
|
<dd>
|
|
|
|
@@ -22,7 +23,7 @@
|
|
href="http://curl.haxx.se/libcurl/c/curl_share_setopt.html"><code>curl_share_setopt</code></a> in libcurl, where
|
|
<em>option</em> is specified with the CURLSHOPT_* constants in libcurl,
|
|
except that the CURLSHOPT_ prefix has been changed to SH_. Currently,
|
|
-<em>value</em> must be either LOCK_DATA_COOKIE or LOCK_DATA_DNS.
|
|
+<em>value</em> must be either LOCK_DATA_COOKIE or LOCK_DATA_DNS.</p>
|
|
|
|
<p>Example usage:</p>
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 87aa7c722ddfefd38faef5a8a038c2e8e64db003 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 30 May 2013 15:27:02 -0400
|
|
Subject: [PATCH 125/149] Use nose test skipping functionality
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/curlopt_test.py | 14 ++++++++------
|
|
tests/global_init_test.py | 11 +++++++----
|
|
2 files changed, 15 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/tests/curlopt_test.py b/tests/curlopt_test.py
|
|
index 9392a39..fd30394 100644
|
|
--- a/tests/curlopt_test.py
|
|
+++ b/tests/curlopt_test.py
|
|
@@ -4,15 +4,17 @@
|
|
|
|
import pycurl
|
|
import unittest
|
|
-import nose.tools
|
|
+import nose.plugins.skip
|
|
|
|
from . import util
|
|
|
|
class CurloptTest(unittest.TestCase):
|
|
def test_username(self):
|
|
# CURLOPT_USERNAME was introduced in libcurl-7.19.1
|
|
- if not util.pycurl_version_less_than(7, 19, 1):
|
|
- assert hasattr(pycurl, 'USERNAME')
|
|
- assert hasattr(pycurl, 'PASSWORD')
|
|
- assert hasattr(pycurl, 'PROXYUSERNAME')
|
|
- assert hasattr(pycurl, 'PROXYPASSWORD')
|
|
+ if util.pycurl_version_less_than(7, 19, 1):
|
|
+ raise nose.plugins.skip.SkipTest('libcurl < 7.19.1')
|
|
+
|
|
+ assert hasattr(pycurl, 'USERNAME')
|
|
+ assert hasattr(pycurl, 'PASSWORD')
|
|
+ assert hasattr(pycurl, 'PROXYUSERNAME')
|
|
+ assert hasattr(pycurl, 'PROXYPASSWORD')
|
|
diff --git a/tests/global_init_test.py b/tests/global_init_test.py
|
|
index b76254b..443ca49 100644
|
|
--- a/tests/global_init_test.py
|
|
+++ b/tests/global_init_test.py
|
|
@@ -5,6 +5,7 @@
|
|
import pycurl
|
|
import unittest
|
|
import nose.tools
|
|
+import nose.plugins.skip
|
|
|
|
from . import util
|
|
|
|
@@ -17,10 +18,12 @@ class GlobalInitTest(unittest.TestCase):
|
|
def test_global_init_ack_eintr(self):
|
|
# the GLOBAL_ACK_EINTR flag was introduced in libcurl-7.30, but can also
|
|
# be backported for older versions of libcurl at the distribution level
|
|
- if not util.pycurl_version_less_than(7, 30) or hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
- # initialize libcurl with the GLOBAL_ACK_EINTR flag
|
|
- pycurl.global_init(pycurl.GLOBAL_ACK_EINTR)
|
|
- pycurl.global_cleanup()
|
|
+ if util.pycurl_version_less_than(7, 30) or hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
+ raise nose.plugins.skip.SkipTest('libcurl < 7.30.0 or no GLOBAL_ACK_EINTR')
|
|
+
|
|
+ # initialize libcurl with the GLOBAL_ACK_EINTR flag
|
|
+ pycurl.global_init(pycurl.GLOBAL_ACK_EINTR)
|
|
+ pycurl.global_cleanup()
|
|
|
|
@nose.tools.raises(ValueError)
|
|
def test_global_init_bogus(self):
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 7e8144d0d83062de394582207197e1081eafcc24 Mon Sep 17 00:00:00 2001
|
|
From: Wim Lewis <wiml@users.sourceforge.net>
|
|
Date: Thu, 21 Jul 2011 12:00:00 -0400
|
|
Subject: [PATCH 126/149] Fix a tiny memory leak in util_curl_init()
|
|
|
|
Each time a new Curl object is created util_curl_init() leaked
|
|
a small string buffer. The attached patch fixes the leak --
|
|
curl_easy_setopt() strdup's its argument; the caller does not need
|
|
to keep the buffer around for it.
|
|
|
|
https://sourceforge.net/p/pycurl/patches/13/
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 9c76609..ef03747 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -793,8 +793,8 @@ util_curl_init(CurlObject *self)
|
|
}
|
|
strcpy(s, "PycURL/"); strcpy(s+7, LIBCURL_VERSION);
|
|
res = curl_easy_setopt(self->handle, CURLOPT_USERAGENT, (char *) s);
|
|
+ free(s);
|
|
if (res != CURLE_OK) {
|
|
- free(s);
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 14e3edf2f77368af4f3838202527c8a48a359d6a Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Fri, 31 May 2013 13:37:39 -0400
|
|
Subject: [PATCH 127/149] Use correct logic when checking for GLOBAL_ACK_EINTR (#34)
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/global_init_test.py | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/tests/global_init_test.py b/tests/global_init_test.py
|
|
index 443ca49..b0d1986 100644
|
|
--- a/tests/global_init_test.py
|
|
+++ b/tests/global_init_test.py
|
|
@@ -18,7 +18,7 @@ class GlobalInitTest(unittest.TestCase):
|
|
def test_global_init_ack_eintr(self):
|
|
# the GLOBAL_ACK_EINTR flag was introduced in libcurl-7.30, but can also
|
|
# be backported for older versions of libcurl at the distribution level
|
|
- if util.pycurl_version_less_than(7, 30) or hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
+ if util.pycurl_version_less_than(7, 30) and not hasattr(pycurl, 'GLOBAL_ACK_EINTR'):
|
|
raise nose.plugins.skip.SkipTest('libcurl < 7.30.0 or no GLOBAL_ACK_EINTR')
|
|
|
|
# initialize libcurl with the GLOBAL_ACK_EINTR flag
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From b2157864dc9b80222d04e6a681d923c1bdc6c64f Mon Sep 17 00:00:00 2001
|
|
From: Roland Sommer <rol@ndsommer.de>
|
|
Date: Wed, 8 May 2013 15:13:14 +0300
|
|
Subject: [PATCH 128/149] Use urlparse.urljoin instead of os.path.join
|
|
|
|
Using a base_url like "http://www.google.de" and calling
|
|
get("/") on a curl.Curl-instance does not work.
|
|
|
|
os.path.join("http://www.google.de", "/") does not yield
|
|
the expected "http://www.google.de/" but "/" which leads to:
|
|
|
|
error: (3, '<url> malformed')
|
|
|
|
Using urljoin fixes this.
|
|
|
|
https://github.com/christophwarner/PyCurl/pull/2
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
python/curl/__init__.py | 6 ++++--
|
|
1 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/python/curl/__init__.py b/python/curl/__init__.py
|
|
index fd179fc..31b9d49 100644
|
|
--- a/python/curl/__init__.py
|
|
+++ b/python/curl/__init__.py
|
|
@@ -6,11 +6,13 @@
|
|
#
|
|
# By Eric S. Raymond, April 2003.
|
|
|
|
-import os, sys, exceptions, mimetools, pycurl
|
|
+import sys, exceptions, mimetools, pycurl
|
|
try:
|
|
import urllib.parse as urllib_parse
|
|
+ from urllib.parse import urljoin
|
|
except ImportError:
|
|
import urllib as urllib_parse
|
|
+ from urlparse import urljoin
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
@@ -81,7 +83,7 @@ class Curl:
|
|
if self.fakeheaders:
|
|
self.set_option(pycurl.HTTPHEADER, self.fakeheaders)
|
|
if relative_url:
|
|
- self.set_option(pycurl.URL,os.path.join(self.base_url,relative_url))
|
|
+ self.set_option(pycurl.URL, urljoin(self.base_url, relative_url))
|
|
self.payload = ""
|
|
self.hdr = ""
|
|
self.handle.perform()
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From b12be12fc45fc786e2d537a3bbd3044488f1e367 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 4 Jun 2013 13:30:39 -0400
|
|
Subject: [PATCH 129/149] Test coverage for relative urls in curl module
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/relative_url_test.py | 24 ++++++++++++++++++++++++
|
|
1 files changed, 24 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/relative_url_test.py
|
|
|
|
diff --git a/tests/relative_url_test.py b/tests/relative_url_test.py
|
|
new file mode 100644
|
|
index 0000000..ddff2b6
|
|
--- /dev/null
|
|
+++ b/tests/relative_url_test.py
|
|
@@ -0,0 +1,24 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+# uses the high level interface
|
|
+import curl
|
|
+import unittest
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+from . import util
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class RelativeUrlTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = curl.Curl('http://localhost:8380/')
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_get_relative(self):
|
|
+ self.curl.get('/success')
|
|
+ self.assertEqual('success', self.curl.body())
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From d29d339d892c52aad6e0be0b22b75dc52e9d9450 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sun, 2 Jun 2013 01:57:16 -0400
|
|
Subject: [PATCH 130/149] Avoid dynamically allocating memory for default pycurl user agent.
|
|
|
|
This implementation requires LIBCURL_VERSION to be a #define.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 11 ++++-------
|
|
1 files changed, 4 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index ef03747..b9d797e 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -105,6 +105,9 @@ static void pycurl_ssl_cleanup(void);
|
|
#define OPTIONS_SIZE ((int)CURLOPT_LASTENTRY % 10000)
|
|
#define MOPTIONS_SIZE ((int)CURLMOPT_LASTENTRY % 10000)
|
|
|
|
+/* Keep some default variables around */
|
|
+static char *g_pycurl_useragent = "PycURL/" LIBCURL_VERSION;
|
|
+
|
|
/* Type objects */
|
|
static PyObject *ErrorObject = NULL;
|
|
static PyTypeObject *p_Curl_Type = NULL;
|
|
@@ -787,13 +790,7 @@ util_curl_init(CurlObject *self)
|
|
}
|
|
|
|
/* Set default USERAGENT */
|
|
- s = (char *) malloc(7 + strlen(LIBCURL_VERSION) + 1);
|
|
- if (s == NULL) {
|
|
- return (-1);
|
|
- }
|
|
- strcpy(s, "PycURL/"); strcpy(s+7, LIBCURL_VERSION);
|
|
- res = curl_easy_setopt(self->handle, CURLOPT_USERAGENT, (char *) s);
|
|
- free(s);
|
|
+ res = curl_easy_setopt(self->handle, CURLOPT_USERAGENT, (char *) g_pycurl_useragent);
|
|
if (res != CURLE_OK) {
|
|
return (-1);
|
|
}
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From f8d2f64764ee25572453317371ff58fe048a8a8a Mon Sep 17 00:00:00 2001
|
|
From: Marien Zwart <marienz@users.sourceforge.net>
|
|
Date: Wed, 13 Jun 2012 00:00:00 -0400
|
|
Subject: [PATCH 131/149] Mark NSS as supported.
|
|
|
|
Mark NSS as supported, as it does not require the application to
|
|
initialize threading.
|
|
|
|
If curl is using nss we do not seem to need to initialize threading
|
|
explicitly: the only threading-related bit I see in the nss
|
|
headers/documentation has to do with simultaneous non-nss use of
|
|
pkcs11 modules, nss itself seems to be thread-safe by default.
|
|
So silence the build warning.
|
|
|
|
http://sourceforge.net/p/pycurl/patches/15/
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
setup.py | 2 ++
|
|
src/pycurl.c | 4 ++--
|
|
2 files changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/setup.py b/setup.py
|
|
index 385facb..40da07a 100644
|
|
--- a/setup.py
|
|
+++ b/setup.py
|
|
@@ -119,6 +119,8 @@ else:
|
|
define_macros.append(('HAVE_CURL_OPENSSL', 1))
|
|
if e[2:] == 'gnutls':
|
|
define_macros.append(('HAVE_CURL_GNUTLS', 1))
|
|
+ if e[2:] == 'ssl3':
|
|
+ define_macros.append(('HAVE_CURL_NSS', 1))
|
|
elif e[:2] == "-L":
|
|
library_dirs.append(e[2:])
|
|
else:
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index b9d797e..a913c47 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -88,12 +88,12 @@ typedef int Py_ssize_t;
|
|
# define PYCURL_NEED_SSL_TSL
|
|
# define PYCURL_NEED_GNUTLS_TSL
|
|
# include <gcrypt.h>
|
|
-# else
|
|
+# elif !defined(HAVE_CURL_NSS)
|
|
# warning \
|
|
"libcurl was compiled with SSL support, but configure could not determine which " \
|
|
"library was used; thus no SSL crypto locking callbacks will be set, which may " \
|
|
"cause random crashes on SSL requests"
|
|
-# endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
|
|
+# endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS || HAVE_CURL_NSS */
|
|
#endif /* HAVE_CURL_SSL */
|
|
|
|
#if defined(PYCURL_NEED_SSL_TSL)
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 256f4bece80ee579daf18cbccc6007c0fa517903 Mon Sep 17 00:00:00 2001
|
|
From: Marien Zwart <marienz@users.sourceforge.net>
|
|
Date: Wed, 13 Jun 2012 00:00:00 -0400
|
|
Subject: [PATCH 132/149] Only initialize gcrypt if we are using an older gnutls that needs this.
|
|
|
|
This is necessary to support newer gnutls linked to libnettle instead
|
|
of libgcrypt.
|
|
|
|
If curl is using a recent version of gnutls we do not need to initialize
|
|
libgcrypt threading: gnutls does that for us. And because recent versions
|
|
of gnutls may be using nettle instead of gcrypt it is important that we
|
|
don't: those functions are not necessarily defined (and linking to
|
|
libgcrypt explicitly to get them is stupid, as they're not used). The
|
|
modification is based on instructions from the gnutls NEWS file.
|
|
|
|
http://sourceforge.net/p/pycurl/patches/15/
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 9 ++++++---
|
|
1 files changed, 6 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index a913c47..5d4e5b0 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -85,9 +85,12 @@ typedef int Py_ssize_t;
|
|
# define PYCURL_NEED_OPENSSL_TSL
|
|
# include <openssl/crypto.h>
|
|
# elif defined(HAVE_CURL_GNUTLS)
|
|
-# define PYCURL_NEED_SSL_TSL
|
|
-# define PYCURL_NEED_GNUTLS_TSL
|
|
-# include <gcrypt.h>
|
|
+# include <gnutls/gnutls.h>
|
|
+# if GNUTLS_VERSION_NUMBER <= 0x020b00
|
|
+# define PYCURL_NEED_SSL_TSL
|
|
+# define PYCURL_NEED_GNUTLS_TSL
|
|
+# include <gcrypt.h>
|
|
+# endif
|
|
# elif !defined(HAVE_CURL_NSS)
|
|
# warning \
|
|
"libcurl was compiled with SSL support, but configure could not determine which " \
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From f4ec6883c9d5ebfa961aa6063313903b2ca7ce1e Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Sun, 9 Jun 2013 17:34:41 +0000
|
|
Subject: [PATCH 133/149] Allow pycURL to be used with Python binaries built without thread support
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 215 ++++++++++++++++++++++++++++++++++++++-------------------
|
|
1 files changed, 143 insertions(+), 72 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 5d4e5b0..a9923ed 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -104,6 +104,30 @@ static void pycurl_ssl_init(void);
|
|
static void pycurl_ssl_cleanup(void);
|
|
#endif
|
|
|
|
+#ifdef WITH_THREAD
|
|
+# define PYCURL_DECLARE_THREAD_STATE PyThreadState *tmp_state
|
|
+# define PYCURL_ACQUIRE_THREAD() acquire_thread(self, &tmp_state)
|
|
+# define PYCURL_ACQUIRE_THREAD_MULTI() acquire_thread_multi(self, &tmp_state)
|
|
+# define PYCURL_RELEASE_THREAD() release_thread(tmp_state)
|
|
+/* Replacement for Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS when python
|
|
+ callbacks are expected during blocking i/o operations: self->state will hold
|
|
+ the handle to current thread to be used as context */
|
|
+# define PYCURL_BEGIN_ALLOW_THREADS \
|
|
+ self->state = PyThreadState_Get(); \
|
|
+ assert(self->state != NULL); \
|
|
+ Py_BEGIN_ALLOW_THREADS
|
|
+# define PYCURL_END_ALLOW_THREADS \
|
|
+ Py_END_ALLOW_THREADS \
|
|
+ self->state = NULL;
|
|
+#else
|
|
+# define PYCURL_DECLARE_THREAD_STATE
|
|
+# define PYCURL_ACQUIRE_THREAD() (1)
|
|
+# define PYCURL_ACQUIRE_THREAD_MULTI() (1)
|
|
+# define PYCURL_RELEASE_THREAD()
|
|
+# define PYCURL_BEGIN_ALLOW_THREADS
|
|
+# define PYCURL_END_ALLOW_THREADS
|
|
+#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)
|
|
@@ -126,14 +150,18 @@ typedef struct {
|
|
PyObject_HEAD
|
|
PyObject *dict; /* Python attributes dictionary */
|
|
CURLSH *share_handle;
|
|
+#ifdef WITH_THREAD
|
|
ShareLock *lock; /* lock object to implement CURLSHOPT_LOCKFUNC */
|
|
+#endif
|
|
} CurlShareObject;
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
PyObject *dict; /* Python attributes dictionary */
|
|
CURLM *multi_handle;
|
|
+#ifdef WITH_THREAD
|
|
PyThreadState *state;
|
|
+#endif
|
|
fd_set read_fd_set;
|
|
fd_set write_fd_set;
|
|
fd_set exc_fd_set;
|
|
@@ -146,7 +174,9 @@ typedef struct {
|
|
PyObject_HEAD
|
|
PyObject *dict; /* Python attributes dictionary */
|
|
CURL *handle;
|
|
+#ifdef WITH_THREAD
|
|
PyThreadState *state;
|
|
+#endif
|
|
CurlMultiObject *multi_stack;
|
|
CurlShareObject *share;
|
|
struct curl_httppost *httppost;
|
|
@@ -261,6 +291,7 @@ error:
|
|
}
|
|
|
|
|
|
+#ifdef WITH_THREAD
|
|
/*************************************************************************
|
|
// static utility functions
|
|
**************************************************************************/
|
|
@@ -317,13 +348,42 @@ get_thread_state_multi(const CurlMultiObject *self)
|
|
}
|
|
|
|
|
|
+static int acquire_thread(const CurlObject *self, PyThreadState **state)
|
|
+{
|
|
+ *state = get_thread_state(self);
|
|
+ if (*state == NULL)
|
|
+ return 0;
|
|
+ PyEval_AcquireThread(*state);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+static int acquire_thread_multi(const CurlMultiObject *self, PyThreadState **state)
|
|
+{
|
|
+ *state = get_thread_state_multi(self);
|
|
+ if (*state == NULL)
|
|
+ return 0;
|
|
+ PyEval_AcquireThread(*state);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+static void release_thread(PyThreadState *state)
|
|
+{
|
|
+ PyEval_ReleaseThread(state);
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
/* assert some CurlShareObject invariants */
|
|
static void
|
|
assert_share_state(const CurlShareObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
assert(self->ob_type == p_CurlShare_Type);
|
|
+#ifdef WITH_THREAD
|
|
assert(self->lock != NULL);
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -333,7 +393,9 @@ assert_curl_state(const CurlObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
assert(self->ob_type == p_Curl_Type);
|
|
+#ifdef WITH_THREAD
|
|
(void) get_thread_state(self);
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -343,9 +405,11 @@ assert_multi_state(const CurlMultiObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
assert(self->ob_type == p_CurlMulti_Type);
|
|
+#ifdef WITH_THREAD
|
|
if (self->state != NULL) {
|
|
assert(self->multi_handle != NULL);
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -358,10 +422,12 @@ check_curl_state(const CurlObject *self, int flags, const char *name)
|
|
PyErr_Format(ErrorObject, "cannot invoke %s() - no curl handle", name);
|
|
return -1;
|
|
}
|
|
+#ifdef WITH_THREAD
|
|
if ((flags & 2) && get_thread_state(self) != NULL) {
|
|
PyErr_Format(ErrorObject, "cannot invoke %s() - perform() is currently running", name);
|
|
return -1;
|
|
}
|
|
+#endif
|
|
return 0;
|
|
}
|
|
|
|
@@ -373,10 +439,12 @@ check_multi_state(const CurlMultiObject *self, int flags, const char *name)
|
|
PyErr_Format(ErrorObject, "cannot invoke %s() - no multi handle", name);
|
|
return -1;
|
|
}
|
|
+#ifdef WITH_THREAD
|
|
if ((flags & 2) && self->state != NULL) {
|
|
PyErr_Format(ErrorObject, "cannot invoke %s() - multi_perform() is currently running", name);
|
|
return -1;
|
|
}
|
|
+#endif
|
|
return 0;
|
|
}
|
|
|
|
@@ -391,6 +459,7 @@ check_share_state(const CurlShareObject *self, int flags, const char *name)
|
|
// SSL TSL
|
|
**************************************************************************/
|
|
|
|
+#ifdef WITH_THREAD
|
|
#ifdef PYCURL_NEED_OPENSSL_TSL
|
|
|
|
static PyThread_type_lock *pycurl_openssl_tsl = NULL;
|
|
@@ -560,6 +629,19 @@ share_unlock_callback(CURL *handle, curl_lock_data data, void *userptr)
|
|
share_lock_unlock(share->lock, data);
|
|
}
|
|
|
|
+#else /* WITH_THREAD */
|
|
+
|
|
+static void pycurl_ssl_init(void)
|
|
+{
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void pycurl_ssl_cleanup(void)
|
|
+{
|
|
+ return;
|
|
+}
|
|
+
|
|
+#endif /* WITH_THREAD */
|
|
|
|
/* constructor - this is a module-level function returning a new instance */
|
|
static CurlShareObject *
|
|
@@ -567,8 +649,10 @@ do_share_new(PyObject *dummy)
|
|
{
|
|
int res;
|
|
CurlShareObject *self;
|
|
+#ifdef WITH_THREAD
|
|
const curl_lock_function lock_cb = share_lock_callback;
|
|
const curl_unlock_function unlock_cb = share_unlock_callback;
|
|
+#endif
|
|
|
|
UNUSED(dummy);
|
|
|
|
@@ -583,8 +667,10 @@ do_share_new(PyObject *dummy)
|
|
|
|
/* Initialize object attributes */
|
|
self->dict = NULL;
|
|
+#ifdef WITH_THREAD
|
|
self->lock = share_lock_new();
|
|
assert(self->lock != NULL);
|
|
+#endif
|
|
|
|
/* Allocate libcurl share handle */
|
|
self->share_handle = curl_share_init();
|
|
@@ -594,6 +680,7 @@ do_share_new(PyObject *dummy)
|
|
return NULL;
|
|
}
|
|
|
|
+#ifdef WITH_THREAD
|
|
/* Set locking functions and data */
|
|
res = curl_share_setopt(self->share_handle, CURLSHOPT_LOCKFUNC, lock_cb);
|
|
assert(res == CURLE_OK);
|
|
@@ -601,6 +688,7 @@ do_share_new(PyObject *dummy)
|
|
assert(res == CURLE_OK);
|
|
res = curl_share_setopt(self->share_handle, CURLSHOPT_UNLOCKFUNC, unlock_cb);
|
|
assert(res == CURLE_OK);
|
|
+#endif
|
|
|
|
return self;
|
|
}
|
|
@@ -632,7 +720,9 @@ do_share_clear(CurlShareObject *self)
|
|
static void
|
|
util_share_close(CurlShareObject *self){
|
|
curl_share_cleanup(self->share_handle);
|
|
+#ifdef WITH_THREAD
|
|
share_lock_destroy(self->lock);
|
|
+#endif
|
|
}
|
|
|
|
|
|
@@ -723,7 +813,9 @@ util_curl_new(void)
|
|
/* Set python curl object initial values */
|
|
self->dict = NULL;
|
|
self->handle = NULL;
|
|
+#ifdef WITH_THREAD
|
|
self->state = NULL;
|
|
+#endif
|
|
self->share = NULL;
|
|
self->multi_stack = NULL;
|
|
self->httppost = NULL;
|
|
@@ -898,12 +990,16 @@ util_curl_close(CurlObject *self)
|
|
if (handle == NULL) {
|
|
/* Some paranoia assertions just to make sure the object
|
|
* deallocation problem is finally really fixed... */
|
|
+#ifdef WITH_THREAD
|
|
assert(self->state == NULL);
|
|
+#endif
|
|
assert(self->multi_stack == NULL);
|
|
assert(self->share == NULL);
|
|
return; /* already closed */
|
|
}
|
|
+#ifdef WITH_THREAD
|
|
self->state = NULL;
|
|
+#endif
|
|
|
|
/* Decref multi stuff which uses this handle */
|
|
util_curl_xdecref(self, 2, handle);
|
|
@@ -977,7 +1073,9 @@ do_curl_errstr(CurlObject *self)
|
|
static int
|
|
do_curl_clear(CurlObject *self)
|
|
{
|
|
+#ifdef WITH_THREAD
|
|
assert(get_thread_state(self) == NULL);
|
|
+#endif
|
|
util_curl_xdecref(self, 1 | 2 | 4 | 8 | 16, self->handle);
|
|
return 0;
|
|
}
|
|
@@ -1020,17 +1118,9 @@ do_curl_perform(CurlObject *self)
|
|
return NULL;
|
|
}
|
|
|
|
- /* Save handle to current thread (used as context for python callbacks) */
|
|
- self->state = PyThreadState_Get();
|
|
- assert(self->state != NULL);
|
|
-
|
|
- /* Release global lock and start */
|
|
- Py_BEGIN_ALLOW_THREADS
|
|
+ PYCURL_BEGIN_ALLOW_THREADS
|
|
res = curl_easy_perform(self->handle);
|
|
- Py_END_ALLOW_THREADS
|
|
-
|
|
- /* Zero thread-state to disallow callbacks to be run from now on */
|
|
- self->state = NULL;
|
|
+ PYCURL_END_ALLOW_THREADS
|
|
|
|
if (res != CURLE_OK) {
|
|
CURLERROR_RETVAL();
|
|
@@ -1050,7 +1140,7 @@ static size_t
|
|
util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
size_t ret = 0; /* assume error */
|
|
@@ -1059,10 +1149,8 @@ util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *strea
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
- tmp_state = get_thread_state(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD())
|
|
return ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
cb = flags ? self->h_cb : self->w_cb;
|
|
@@ -1101,7 +1189,7 @@ util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *strea
|
|
done:
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -1131,13 +1219,12 @@ opensocket_callback(void *clientp, curlsocktype purpose,
|
|
PyObject *result = NULL;
|
|
PyObject *fileno_result = NULL;
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
int ret = CURL_SOCKET_BAD;
|
|
|
|
self = (CurlObject *)clientp;
|
|
- tmp_state = get_thread_state(self);
|
|
+ PYCURL_ACQUIRE_THREAD();
|
|
|
|
- PyEval_AcquireThread(tmp_state);
|
|
arglist = Py_BuildValue("(iii)", address->family, address->socktype, address->protocol);
|
|
if (arglist == NULL)
|
|
goto verbose_error;
|
|
@@ -1171,7 +1258,7 @@ silent_error:
|
|
done:
|
|
Py_XDECREF(result);
|
|
Py_XDECREF(fileno_result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -1182,7 +1269,7 @@ static int
|
|
seek_callback(void *stream, curl_off_t offset, int origin)
|
|
{
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 2; /* assume error 2 (can't seek, libcurl free to work around). */
|
|
@@ -1191,10 +1278,8 @@ seek_callback(void *stream, curl_off_t offset, int origin)
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
- tmp_state = get_thread_state(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD())
|
|
return ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check arguments */
|
|
switch (origin)
|
|
@@ -1244,7 +1329,7 @@ seek_callback(void *stream, curl_off_t offset, int origin)
|
|
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -1258,7 +1343,7 @@ static size_t
|
|
read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
|
|
@@ -1267,10 +1352,8 @@ read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
- tmp_state = get_thread_state(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD())
|
|
return ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
if (self->r_cb == NULL)
|
|
@@ -1328,7 +1411,7 @@ read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
done:
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -1341,17 +1424,15 @@ progress_callback(void *stream,
|
|
double dltotal, double dlnow, double ultotal, double ulnow)
|
|
{
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 1; /* assume error */
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
- tmp_state = get_thread_state(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD())
|
|
return ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
if (self->pro_cb == NULL)
|
|
@@ -1379,7 +1460,7 @@ progress_callback(void *stream,
|
|
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -1392,7 +1473,7 @@ debug_callback(CURL *curlobj, curl_infotype type,
|
|
char *buffer, size_t total_size, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 0; /* always success */
|
|
@@ -1401,10 +1482,8 @@ debug_callback(CURL *curlobj, curl_infotype type,
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
- tmp_state = get_thread_state(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD())
|
|
return ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
if (self->debug_cb == NULL)
|
|
@@ -1427,7 +1506,7 @@ debug_callback(CURL *curlobj, curl_infotype type,
|
|
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -1439,7 +1518,7 @@ static curlioerr
|
|
ioctl_callback(CURL *curlobj, int cmd, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = CURLIOE_FAILRESTART; /* assume error */
|
|
@@ -1448,10 +1527,8 @@ ioctl_callback(CURL *curlobj, int cmd, void *stream)
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
- tmp_state = get_thread_state(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD())
|
|
return (curlioerr) ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
if (self->ioctl_cb == NULL)
|
|
@@ -1480,7 +1557,7 @@ ioctl_callback(CURL *curlobj, int cmd, void *stream)
|
|
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return (curlioerr) ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -2324,7 +2401,9 @@ do_multi_new(PyObject *dummy)
|
|
|
|
/* Initialize object attributes */
|
|
self->dict = NULL;
|
|
+#ifdef WITH_THREAD
|
|
self->state = NULL;
|
|
+#endif
|
|
self->t_cb = NULL;
|
|
self->s_cb = NULL;
|
|
|
|
@@ -2342,7 +2421,9 @@ static void
|
|
util_multi_close(CurlMultiObject *self)
|
|
{
|
|
assert(self != NULL);
|
|
+#ifdef WITH_THREAD
|
|
self->state = NULL;
|
|
+#endif
|
|
if (self->multi_handle != NULL) {
|
|
CURLM *multi_handle = self->multi_handle;
|
|
self->multi_handle = NULL;
|
|
@@ -2411,7 +2492,7 @@ int multi_socket_callback(CURL *easy,
|
|
{
|
|
CurlMultiObject *self;
|
|
CurlObject *easy_self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret;
|
|
@@ -2419,10 +2500,8 @@ int multi_socket_callback(CURL *easy,
|
|
/* acquire thread */
|
|
self = (CurlMultiObject *)userp;
|
|
ret = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &easy_self);
|
|
- tmp_state = get_thread_state_multi(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD_MULTI())
|
|
return 0;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
if (self->s_cb == NULL)
|
|
@@ -2446,7 +2525,7 @@ int multi_socket_callback(CURL *easy,
|
|
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return 0;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -2460,7 +2539,7 @@ int multi_timer_callback(CURLM *multi,
|
|
void *userp)
|
|
{
|
|
CurlMultiObject *self;
|
|
- PyThreadState *tmp_state;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 0; /* always success */
|
|
@@ -2469,10 +2548,8 @@ int multi_timer_callback(CURLM *multi,
|
|
|
|
/* acquire thread */
|
|
self = (CurlMultiObject *)userp;
|
|
- tmp_state = get_thread_state_multi(self);
|
|
- if (tmp_state == NULL)
|
|
+ if (!PYCURL_ACQUIRE_THREAD_MULTI())
|
|
return ret;
|
|
- PyEval_AcquireThread(tmp_state);
|
|
|
|
/* check args */
|
|
if (self->t_cb == NULL)
|
|
@@ -2491,7 +2568,7 @@ int multi_timer_callback(CURLM *multi,
|
|
|
|
silent_error:
|
|
Py_XDECREF(result);
|
|
- PyEval_ReleaseThread(tmp_state);
|
|
+ PYCURL_RELEASE_THREAD();
|
|
return ret;
|
|
verbose_error:
|
|
PyErr_Print();
|
|
@@ -2634,14 +2711,10 @@ do_multi_socket_action(CurlMultiObject *self, PyObject *args)
|
|
if (check_multi_state(self, 1 | 2, "socket_action") != 0) {
|
|
return NULL;
|
|
}
|
|
- /* Release global lock and start */
|
|
- self->state = PyThreadState_Get();
|
|
- assert(self->state != NULL);
|
|
- Py_BEGIN_ALLOW_THREADS
|
|
|
|
+ PYCURL_BEGIN_ALLOW_THREADS
|
|
res = curl_multi_socket_action(self->multi_handle, socket, ev_bitmask, &running);
|
|
- Py_END_ALLOW_THREADS
|
|
- self->state = NULL;
|
|
+ PYCURL_END_ALLOW_THREADS
|
|
|
|
if (res != CURLM_OK) {
|
|
CURLERROR_MSG("multi_socket_action failed");
|
|
@@ -2662,13 +2735,9 @@ do_multi_socket_all(CurlMultiObject *self)
|
|
return NULL;
|
|
}
|
|
|
|
- /* Release global lock and start */
|
|
- self->state = PyThreadState_Get();
|
|
- assert(self->state != NULL);
|
|
- Py_BEGIN_ALLOW_THREADS
|
|
+ PYCURL_BEGIN_ALLOW_THREADS
|
|
res = curl_multi_socket_all(self->multi_handle, &running);
|
|
- Py_END_ALLOW_THREADS
|
|
- self->state = NULL;
|
|
+ PYCURL_END_ALLOW_THREADS
|
|
|
|
/* We assume these errors are ok, otherwise throw exception */
|
|
if (res != CURLM_OK && res != CURLM_CALL_MULTI_PERFORM) {
|
|
@@ -2692,13 +2761,9 @@ do_multi_perform(CurlMultiObject *self)
|
|
return NULL;
|
|
}
|
|
|
|
- /* Release global lock and start */
|
|
- self->state = PyThreadState_Get();
|
|
- assert(self->state != NULL);
|
|
- Py_BEGIN_ALLOW_THREADS
|
|
+ PYCURL_BEGIN_ALLOW_THREADS
|
|
res = curl_multi_perform(self->multi_handle, &running);
|
|
- Py_END_ALLOW_THREADS
|
|
- self->state = NULL;
|
|
+ PYCURL_END_ALLOW_THREADS
|
|
|
|
/* We assume these errors are ok, otherwise throw exception */
|
|
if (res != CURLM_OK && res != CURLM_CALL_MULTI_PERFORM) {
|
|
@@ -2722,16 +2787,20 @@ check_multi_add_remove(const CurlMultiObject *self, const CurlObject *obj)
|
|
PyErr_SetString(ErrorObject, "cannot add/remove handle - multi-stack is closed");
|
|
return -1;
|
|
}
|
|
+#ifdef WITH_THREAD
|
|
if (self->state != NULL) {
|
|
PyErr_SetString(ErrorObject, "cannot add/remove handle - multi_perform() already running");
|
|
return -1;
|
|
}
|
|
+#endif
|
|
/* check CurlObject status */
|
|
assert_curl_state(obj);
|
|
+#ifdef WITH_THREAD
|
|
if (obj->state != NULL) {
|
|
PyErr_SetString(ErrorObject, "cannot add/remove handle - perform() of curl object already running");
|
|
return -1;
|
|
}
|
|
+#endif
|
|
if (obj->multi_stack != NULL && obj->multi_stack != self) {
|
|
PyErr_SetString(ErrorObject, "cannot add/remove handle - curl object already on another multi-stack");
|
|
return -1;
|
|
@@ -3989,8 +4058,10 @@ initpycurl(void)
|
|
pycurl_ssl_init();
|
|
#endif
|
|
|
|
+#ifdef WITH_THREAD
|
|
/* Finally initialize global interpreter lock */
|
|
PyEval_InitThreads();
|
|
+#endif
|
|
|
|
}
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 9c06c6f29f4fcb5b6be9200f96c19b54b71e4b3b Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 12 Jun 2013 00:48:14 -0400
|
|
Subject: [PATCH 134/149] Test for seek function
|
|
|
|
Original patch by Jonas <seventies@users.sourceforge.net>.
|
|
|
|
http://sourceforge.net/p/pycurl/patches/8/
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
.gitignore | 1 +
|
|
Makefile | 1 +
|
|
tests/seek_function_test.py | 72 +++++++++++++++++++++++++++++++++++++++++++
|
|
tests/vsftpd.conf | 4 ++-
|
|
4 files changed, 77 insertions(+), 1 deletions(-)
|
|
create mode 100644 tests/seek_function_test.py
|
|
|
|
diff --git a/.gitignore b/.gitignore
|
|
index c873e32..abc741a 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -3,6 +3,7 @@
|
|
/MANIFEST
|
|
/build
|
|
/dist
|
|
+/tests/tmp
|
|
/www/htdocs/download/*.bz2
|
|
/www/htdocs/download/*.exe
|
|
/www/htdocs/download/*.gz
|
|
diff --git a/Makefile b/Makefile
|
|
index 9475250..cb12aaf 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -16,6 +16,7 @@ build-7.10.8:
|
|
$(PYTHON) setup.py build --curl-config=/home/hosts/localhost/packages/curl-7.10.8/bin/curl-config
|
|
|
|
test: build
|
|
+ mkdir -p tests/tmp
|
|
PYTHONPATH=$$(ls -d build/lib.*):$$PYTHONPATH \
|
|
$(NOSETESTS)
|
|
|
|
diff --git a/tests/seek_function_test.py b/tests/seek_function_test.py
|
|
new file mode 100644
|
|
index 0000000..2a28078
|
|
--- /dev/null
|
|
+++ b/tests/seek_function_test.py
|
|
@@ -0,0 +1,72 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+# Note: this test is meant to be run from pycurl project root.
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import os.path
|
|
+
|
|
+from . import util
|
|
+from . import procmgr
|
|
+
|
|
+setup_module, teardown_module = procmgr.vsftpd_setup()
|
|
+
|
|
+class PartialFileSource:
|
|
+ def __init__(self):
|
|
+ self.__buf = '1234567890.1234567890'
|
|
+ self.__maxread = None
|
|
+ self.__bufptr = 0
|
|
+
|
|
+ def read(self, size):
|
|
+ p = self.__bufptr
|
|
+ end = p+size
|
|
+ if self.__maxread:
|
|
+ end = min(self.__maxread, end)
|
|
+ ret = self.__buf[p:end]
|
|
+ self.__bufptr+= len(ret)
|
|
+ #print 20*">>>", "read(%s) ==> %s" % (size, len(ret))
|
|
+ return ret
|
|
+
|
|
+ def seek(self, offset, origin):
|
|
+ #print 20*">>>", "seek(%s, %s)" % (offset, origin)
|
|
+ self.__bufptr = offset
|
|
+
|
|
+ def set_maxread(self, maxread):
|
|
+ self.__maxread = maxread
|
|
+
|
|
+class SeekFunctionTest(unittest.TestCase):
|
|
+ def test_seek_function(self):
|
|
+ c = pycurl.Curl()
|
|
+ c.setopt(pycurl.UPLOAD, 1)
|
|
+ c.setopt(pycurl.URL, "ftp://localhost:8321/tests/tmp/upload.txt")
|
|
+ c.setopt(pycurl.RESUME_FROM, 0)
|
|
+ #c.setopt(pycurl.VERBOSE, 1)
|
|
+ upload_file = PartialFileSource()
|
|
+ c.setopt(pycurl.READFUNCTION, upload_file.read)
|
|
+ upload_file.set_maxread(10)
|
|
+ c.perform()
|
|
+
|
|
+ with open(os.path.join(os.path.dirname(__file__), 'tmp', 'upload.txt')) as f:
|
|
+ content = f.read()
|
|
+ self.assertEqual('1234567890', content)
|
|
+
|
|
+ c.close()
|
|
+ del c
|
|
+ del upload_file
|
|
+
|
|
+ c = pycurl.Curl()
|
|
+ c.setopt(pycurl.URL, "ftp://localhost:8321/tests/tmp/upload.txt")
|
|
+ c.setopt(pycurl.RESUME_FROM, -1)
|
|
+ c.setopt(pycurl.UPLOAD, 1)
|
|
+ #c.setopt(pycurl.VERBOSE, 1)
|
|
+ upload_file = PartialFileSource()
|
|
+ c.setopt(pycurl.READFUNCTION, upload_file.read)
|
|
+ c.setopt(pycurl.SEEKFUNCTION, upload_file.seek)
|
|
+ c.perform()
|
|
+ c.close()
|
|
+
|
|
+ with open(os.path.join(os.path.dirname(__file__), 'tmp', 'upload.txt')) as f:
|
|
+ content = f.read()
|
|
+ self.assertEqual('1234567890.1234567890', content)
|
|
diff --git a/tests/vsftpd.conf b/tests/vsftpd.conf
|
|
index b4e4972..787da0e 100644
|
|
--- a/tests/vsftpd.conf
|
|
+++ b/tests/vsftpd.conf
|
|
@@ -5,7 +5,9 @@ background=no
|
|
download_enable=no
|
|
listen=yes
|
|
run_as_launching_user=yes
|
|
-write_enable=no
|
|
+write_enable=yes
|
|
+anon_upload_enable=yes
|
|
+anon_other_write_enable=yes
|
|
listen_port=8321
|
|
# should be supplied on command line
|
|
anon_root=/var/empty
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 7445cc96205e9c2b734ec07955519db224aa3ab7 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 12 Jun 2013 18:01:16 -0400
|
|
Subject: [PATCH 135/149] Allow multiple ftp tests to work in the suite
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/procmgr.py | 15 ++++++++++-----
|
|
1 files changed, 10 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/tests/procmgr.py b/tests/procmgr.py
|
|
index ce08da9..18c3dd2 100644
|
|
--- a/tests/procmgr.py
|
|
+++ b/tests/procmgr.py
|
|
@@ -12,6 +12,7 @@ class ProcessManager(object):
|
|
|
|
def start(self):
|
|
self.process = subprocess.Popen(self.cmd)
|
|
+ self.running = True
|
|
|
|
self.thread = threading.Thread(target=self.run)
|
|
self.thread.daemon = True
|
|
@@ -19,11 +20,18 @@ class ProcessManager(object):
|
|
|
|
def run(self):
|
|
self.process.communicate()
|
|
+
|
|
+ def stop(self):
|
|
+ try:
|
|
+ os.kill(self.process.pid, signal.SIGTERM)
|
|
+ except OSError:
|
|
+ pass
|
|
+ self.running = False
|
|
|
|
managers = {}
|
|
|
|
def start(cmd):
|
|
- if str(cmd) in managers:
|
|
+ if str(cmd) in managers and managers[str(cmd)].running:
|
|
# already started
|
|
return
|
|
|
|
@@ -75,9 +83,6 @@ def vsftpd_setup():
|
|
except KeyError:
|
|
pass
|
|
else:
|
|
- try:
|
|
- os.kill(manager.process.pid, signal.SIGTERM)
|
|
- except OSError:
|
|
- pass
|
|
+ manager.stop()
|
|
|
|
return do_setup_module, teardown_module
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 4f8e4def8eddac6d5e5239602ef00230a2be3690 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Wed, 12 Jun 2013 19:26:25 -0400
|
|
Subject: [PATCH 136/149] Do not run vsftpd tests by default due to security implications
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
README.rst | 18 ++++++++++++++++++
|
|
tests/procmgr.py | 14 +++++++++++++-
|
|
2 files changed, 31 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/README.rst b/README.rst
|
|
index 3518d9d..c4427aa 100644
|
|
--- a/README.rst
|
|
+++ b/README.rst
|
|
@@ -49,6 +49,24 @@ or `pip`_::
|
|
.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
|
|
.. _pip: http://pypi.python.org/pypi/pip
|
|
|
|
+Automated Tests
|
|
+---------------
|
|
+
|
|
+PycURL comes with an automated test suite. To run the tests, execute::
|
|
+
|
|
+ make test
|
|
+
|
|
+Some tests use vsftpd configured to accept anonymous uploads. These tests
|
|
+are not run by default. As configured, vsftpd will allow reads and writes to
|
|
+anything the user running the tests has read and write access. To run
|
|
+vsftpd tests you must explicitly set PYCURL_VSFTPD_PATH variable like so::
|
|
+
|
|
+ # use vsftpd in PATH
|
|
+ export PYCURL_VSFTPD_PATH=vsftpd
|
|
+
|
|
+ # specify full path to vsftpd
|
|
+ export PYCURL_VSFTPD_PATH=/usr/local/libexec/vsftpd
|
|
+
|
|
Contribute
|
|
----------
|
|
|
|
diff --git a/tests/procmgr.py b/tests/procmgr.py
|
|
index 18c3dd2..9309aa8 100644
|
|
--- a/tests/procmgr.py
|
|
+++ b/tests/procmgr.py
|
|
@@ -3,6 +3,7 @@ import subprocess
|
|
import os
|
|
import sys
|
|
import signal
|
|
+import nose.plugins.skip
|
|
|
|
from . import runwsgi
|
|
|
|
@@ -50,7 +51,16 @@ def start_setup(cmd):
|
|
if 'PYCURL_VSFTPD_PATH' in os.environ:
|
|
vsftpd_path = os.environ['PYCURL_VSFTPD_PATH']
|
|
else:
|
|
- vsftpd_path = 'vsftpd'
|
|
+ vsftpd_path = None
|
|
+
|
|
+try:
|
|
+ # python 2
|
|
+ exception_base = StandardError
|
|
+except NameError:
|
|
+ # python 3
|
|
+ exception_base = Exception
|
|
+class VsftpdNotConfigured(exception_base):
|
|
+ pass
|
|
|
|
def vsftpd_setup():
|
|
config_file_path = os.path.join(os.path.dirname(__file__), 'vsftpd.conf')
|
|
@@ -62,6 +72,8 @@ def vsftpd_setup():
|
|
]
|
|
setup_module = start_setup(cmd)
|
|
def do_setup_module():
|
|
+ if vsftpd_path is None:
|
|
+ raise nose.plugins.skip.SkipTest('PYCURL_VSFTPD_PATH environment variable not set')
|
|
try:
|
|
setup_module()
|
|
except OSError:
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 079b262507e77a61772255aea969471b2d81f16c Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Tue, 16 Jul 2013 11:05:54 -0300
|
|
Subject: [PATCH 137/149] Adjusted declaration order for C89 compilers
|
|
|
|
PYCURL_DECLARE_THREAD_STATE looks like an
|
|
executable statement for some non-C99 compilers
|
|
(e.g. armcc), so it must appear at the end of
|
|
the declaration list.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 19 ++++++++++---------
|
|
1 files changed, 10 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index a9923ed..cdb934e 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -1140,12 +1140,12 @@ static size_t
|
|
util_write_callback(int flags, char *ptr, size_t size, size_t nmemb, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
size_t ret = 0; /* assume error */
|
|
PyObject *cb;
|
|
int total_size;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
@@ -1219,8 +1219,8 @@ opensocket_callback(void *clientp, curlsocktype purpose,
|
|
PyObject *result = NULL;
|
|
PyObject *fileno_result = NULL;
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
int ret = CURL_SOCKET_BAD;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
self = (CurlObject *)clientp;
|
|
PYCURL_ACQUIRE_THREAD();
|
|
@@ -1269,12 +1269,12 @@ static int
|
|
seek_callback(void *stream, curl_off_t offset, int origin)
|
|
{
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 2; /* assume error 2 (can't seek, libcurl free to work around). */
|
|
PyObject *cb;
|
|
int source = 0; /* assume beginning */
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
@@ -1343,13 +1343,14 @@ static size_t
|
|
read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
|
|
size_t ret = CURL_READFUNC_ABORT; /* assume error, this actually works */
|
|
int total_size;
|
|
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
+
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
if (!PYCURL_ACQUIRE_THREAD())
|
|
@@ -1424,10 +1425,10 @@ progress_callback(void *stream,
|
|
double dltotal, double dlnow, double ultotal, double ulnow)
|
|
{
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 1; /* assume error */
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
/* acquire thread */
|
|
self = (CurlObject *)stream;
|
|
@@ -1473,10 +1474,10 @@ debug_callback(CURL *curlobj, curl_infotype type,
|
|
char *buffer, size_t total_size, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 0; /* always success */
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
UNUSED(curlobj);
|
|
|
|
@@ -1518,10 +1519,10 @@ static curlioerr
|
|
ioctl_callback(CURL *curlobj, int cmd, void *stream)
|
|
{
|
|
CurlObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = CURLIOE_FAILRESTART; /* assume error */
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
UNUSED(curlobj);
|
|
|
|
@@ -2492,10 +2493,10 @@ int multi_socket_callback(CURL *easy,
|
|
{
|
|
CurlMultiObject *self;
|
|
CurlObject *easy_self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret;
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
/* acquire thread */
|
|
self = (CurlMultiObject *)userp;
|
|
@@ -2539,10 +2540,10 @@ int multi_timer_callback(CURLM *multi,
|
|
void *userp)
|
|
{
|
|
CurlMultiObject *self;
|
|
- PYCURL_DECLARE_THREAD_STATE;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
int ret = 0; /* always success */
|
|
+ PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
UNUSED(multi);
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 350016b90e38505eeee46358d5303de2a7faca5e Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Tue, 16 Jul 2013 11:13:52 -0300
|
|
Subject: [PATCH 138/149] Silence compiler hints about unused variables
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 4 +---
|
|
1 files changed, 1 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index cdb934e..7b96b01 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -851,7 +851,6 @@ static int
|
|
util_curl_init(CurlObject *self)
|
|
{
|
|
int res;
|
|
- char *s = NULL;
|
|
|
|
/* Set curl error buffer and zero it */
|
|
res = curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->error);
|
|
@@ -2495,12 +2494,11 @@ int multi_socket_callback(CURL *easy,
|
|
CurlObject *easy_self;
|
|
PyObject *arglist;
|
|
PyObject *result = NULL;
|
|
- int ret;
|
|
PYCURL_DECLARE_THREAD_STATE;
|
|
|
|
/* acquire thread */
|
|
self = (CurlMultiObject *)userp;
|
|
- ret = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &easy_self);
|
|
+ curl_easy_getinfo(easy, CURLINFO_PRIVATE, &easy_self);
|
|
if (!PYCURL_ACQUIRE_THREAD_MULTI())
|
|
return 0;
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 19af5bbbc98dc2198cc7541b81ed313a75faeb9c Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Tue, 16 Jul 2013 11:44:36 -0300
|
|
Subject: [PATCH 139/149] Added support for CURLOPT_RESOLVE
|
|
|
|
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTRESOLVE
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 36 ++++++++++++++++++++++++++++++++----
|
|
1 files changed, 32 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 7b96b01..bb6056e 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -68,6 +68,10 @@
|
|
#define HAVE_CURLOPT_PROXYUSERNAME
|
|
#endif
|
|
|
|
+#if LIBCURL_VERSION_NUM >= 0x071503 /* check for 7.21.3 or greater */
|
|
+#define HAVE_CURLOPT_RESOLVE
|
|
+#endif
|
|
+
|
|
/* Python < 2.5 compat for Py_ssize_t */
|
|
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
|
|
typedef int Py_ssize_t;
|
|
@@ -185,6 +189,9 @@ typedef struct {
|
|
struct curl_slist *quote;
|
|
struct curl_slist *postquote;
|
|
struct curl_slist *prequote;
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ struct curl_slist *resolve;
|
|
+#endif
|
|
/* callbacks */
|
|
PyObject *w_cb;
|
|
PyObject *h_cb;
|
|
@@ -824,6 +831,9 @@ util_curl_new(void)
|
|
self->quote = NULL;
|
|
self->postquote = NULL;
|
|
self->prequote = NULL;
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ self->resolve = NULL;
|
|
+#endif
|
|
|
|
/* Set callback pointers to NULL by default */
|
|
self->w_cb = NULL;
|
|
@@ -1025,6 +1035,9 @@ util_curl_close(CurlObject *self)
|
|
SFREE(self->quote);
|
|
SFREE(self->postquote);
|
|
SFREE(self->prequote);
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ SFREE(self->resolve);
|
|
+#endif
|
|
#undef SFREE
|
|
}
|
|
|
|
@@ -1588,6 +1601,9 @@ do_curl_reset(CurlObject *self)
|
|
SFREE(self->quote);
|
|
SFREE(self->postquote);
|
|
SFREE(self->prequote);
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ SFREE(self->resolve);
|
|
+#endif
|
|
#undef SFREE
|
|
res = util_curl_init(self);
|
|
if (res < 0) {
|
|
@@ -1933,6 +1949,11 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
case CURLOPT_PREQUOTE:
|
|
old_slist = &self->prequote;
|
|
break;
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ case CURLOPT_RESOLVE:
|
|
+ old_slist = &self->resolve;
|
|
+ break;
|
|
+#endif
|
|
case CURLOPT_HTTPPOST:
|
|
break;
|
|
default:
|
|
@@ -1944,10 +1965,14 @@ do_curl_setopt(CurlObject *self, PyObject *args)
|
|
len = PyList_Size(obj);
|
|
if (len == 0) {
|
|
/* Empty list - do nothing */
|
|
- if (!(option == CURLOPT_HTTPHEADER ||
|
|
- option == CURLOPT_QUOTE ||
|
|
- option == CURLOPT_POSTQUOTE ||
|
|
- option == CURLOPT_PREQUOTE)) {
|
|
+ if (!(option == CURLOPT_HTTPHEADER
|
|
+ || option == CURLOPT_QUOTE
|
|
+ || option == CURLOPT_POSTQUOTE
|
|
+ || option == CURLOPT_PREQUOTE
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ || option == CURLOPT_RESOLVE
|
|
+#endif
|
|
+ )) {
|
|
/* Empty list - do nothing */
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
@@ -3888,6 +3913,9 @@ initpycurl(void)
|
|
insint_c(d, "CRLFILE", CURLOPT_CRLFILE);
|
|
insint_c(d, "ISSUERCERT", CURLOPT_ISSUERCERT);
|
|
insint_c(d, "ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE);
|
|
+#ifdef HAVE_CURLOPT_RESOLVE
|
|
+ insint_c(d, "RESOLVE", CURLOPT_RESOLVE);
|
|
+#endif
|
|
|
|
insint_c(d, "M_TIMERFUNCTION", CURLMOPT_TIMERFUNCTION);
|
|
insint_c(d, "M_SOCKETFUNCTION", CURLMOPT_SOCKETFUNCTION);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 576efa57797d878e23dd97b1f5ec2393167b30c6 Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Fri, 19 Jul 2013 11:36:43 -0300
|
|
Subject: [PATCH 140/149] Added test-case for CURLOPT_RESOLVE
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/resolve_test.py | 22 ++++++++++++++++++++++
|
|
1 files changed, 22 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/resolve_test.py
|
|
|
|
diff --git a/tests/resolve_test.py b/tests/resolve_test.py
|
|
new file mode 100644
|
|
index 0000000..fcee830
|
|
--- /dev/null
|
|
+++ b/tests/resolve_test.py
|
|
@@ -0,0 +1,22 @@
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+
|
|
+from . import app
|
|
+from . import runwsgi
|
|
+
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8380))
|
|
+
|
|
+class ResolveTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_resolve(self):
|
|
+ self.curl.setopt(pycurl.URL, 'http://p.localhost:8380/success')
|
|
+ self.curl.setopt(pycurl.RESOLVE, ['p.localhost:8380:127.0.0.1'])
|
|
+ self.curl.perform()
|
|
+ self.assertEqual(200, self.curl.getinfo(pycurl.RESPONSE_CODE))
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2ebc6b6097df0a83a6982e8941af3e880e18a74f Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Fri, 19 Jul 2013 11:24:40 -0300
|
|
Subject: [PATCH 141/149] Test suite documentation
|
|
|
|
Briefly clarified documentation about dependencies
|
|
of the test suite.
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
README.rst | 5 +++++
|
|
1 files changed, 5 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/README.rst b/README.rst
|
|
index c4427aa..b416b97 100644
|
|
--- a/README.rst
|
|
+++ b/README.rst
|
|
@@ -56,6 +56,8 @@ PycURL comes with an automated test suite. To run the tests, execute::
|
|
|
|
make test
|
|
|
|
+The suite depends on packages `nose`_ and `bottle`_.
|
|
+
|
|
Some tests use vsftpd configured to accept anonymous uploads. These tests
|
|
are not run by default. As configured, vsftpd will allow reads and writes to
|
|
anything the user running the tests has read and write access. To run
|
|
@@ -67,6 +69,9 @@ vsftpd tests you must explicitly set PYCURL_VSFTPD_PATH variable like so::
|
|
# specify full path to vsftpd
|
|
export PYCURL_VSFTPD_PATH=/usr/local/libexec/vsftpd
|
|
|
|
+.. _nose: https://nose.readthedocs.org/
|
|
+.. _bottle: http://bottlepy.org/
|
|
+
|
|
Contribute
|
|
----------
|
|
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 59fd64c38e4adf28242dca3fd3d3a0167016945a Mon Sep 17 00:00:00 2001
|
|
From: Wim Lewis <wiml@users.sourceforge.net>
|
|
Date: Thu, 21 Jul 2011 12:00:00 -0400
|
|
Subject: [PATCH 142/149] Add suport for CURLINFO_CERTINFO and CURLOPT_CERTINFO.
|
|
|
|
This patch adds support for CURLINFO_CERTINFO (and CURLOPT_CERTINFO),
|
|
as well as documentation for them and a couple of minor documentation fixes.
|
|
These options appeared in libcurl 7.19.1.
|
|
|
|
The format of the returned information was chosen to be reasonably close
|
|
to the underlying libcurl data structure, while also allowing a
|
|
Python programmer to pass the cerificate info to dict() in order to get
|
|
a more convenient representation.
|
|
|
|
https://sourceforge.net/p/pycurl/patches/14/
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
doc/curlobject.html | 19 ++++++++++-
|
|
src/pycurl.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 100 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/doc/curlobject.html b/doc/curlobject.html
|
|
index a3d421f..394b950 100644
|
|
--- a/doc/curlobject.html
|
|
+++ b/doc/curlobject.html
|
|
@@ -43,9 +43,11 @@ href="http://curl.haxx.se/libcurl/c/curl_easy_reset.html"><code>curl_easy_reset<
|
|
<p>Corresponds to
|
|
<a href="http://curl.haxx.se/libcurl/c/curl_easy_setopt.html"><code>curl_easy_setopt</code></a> in libcurl, where
|
|
<em>option</em> is specified with the CURLOPT_* constants in libcurl,
|
|
-except that the CURLOPT_ prefix has been removed. The type for
|
|
+except that the CURLOPT_ prefix has been removed.
|
|
+(See below for exceptions.)
|
|
+The type for
|
|
<em>value</em> depends on the option, and can be either a string,
|
|
-integer, long integer, file objects, lists, or functions.</p>
|
|
+integer, long integer, file object, list, or function.</p>
|
|
|
|
<p>Example usage:</p>
|
|
|
|
@@ -72,6 +74,7 @@ print b.getvalue()
|
|
<a href="http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html"><code>curl_easy_getinfo</code></a> in libcurl, where
|
|
<em>option</em> is the same as the CURLINFO_* constants in libcurl,
|
|
except that the CURLINFO_ prefix has been removed.
|
|
+(See below for exceptions.)
|
|
<em>Result</em> contains an integer, float or string, depending on
|
|
which option is given. The <code>getinfo</code> method should
|
|
not be called unless <code>perform</code> has been called and
|
|
@@ -97,6 +100,18 @@ print c.getinfo(pycurl.HTTP_CODE), c.getinfo(pycurl.EFFECTIVE_URL)
|
|
</dd>
|
|
</dl>
|
|
|
|
+<p>In order to distinguish between similarly-named CURLOPT and
|
|
+CURLINFO constants, some have <code>OPT_</code>
|
|
+and <code>INFO_</code> prefixes. These are
|
|
+<code>INFO_FILETIME</code>, <code>OPT_FILETIME</code>,
|
|
+<code>INFO_COOKIELIST</code> (but <code>setopt</code> uses <code>COOKIELIST</code>!),
|
|
+<code>INFO_CERTINFO</code>, and <code>OPT_CERTINFO</code>.</p>
|
|
+
|
|
+<p>The value returned by <code>getinfo(INFO_CERTINFO)</code> is a list
|
|
+with one element per certificate in the chain, starting with the leaf;
|
|
+each element is a sequence
|
|
+of <code>(</code><em>key</em><code>, </code><em>value</em><code>)</code>
|
|
+tuples.</p>
|
|
|
|
<hr />
|
|
<p>
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index bb6056e..5da354d 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -297,6 +297,71 @@ error:
|
|
return NULL;
|
|
}
|
|
|
|
+/* Convert a struct curl_certinfo into a Python data structure.
|
|
+ * In case of error return NULL with an exception set.
|
|
+ */
|
|
+static PyObject *convert_certinfo(struct curl_certinfo *cinfo)
|
|
+{
|
|
+ PyObject *certs;
|
|
+ int cert_index;
|
|
+
|
|
+ if (!cinfo) {
|
|
+ certs = Py_None;
|
|
+ Py_INCREF(certs);
|
|
+ return certs;
|
|
+ }
|
|
+
|
|
+ certs = PyList_New((Py_ssize_t)(cinfo->num_of_certs));
|
|
+ if (!certs)
|
|
+ return NULL;
|
|
+
|
|
+ for (cert_index = 0; cert_index < cinfo->num_of_certs; cert_index ++) {
|
|
+ struct curl_slist *fields = cinfo->certinfo[cert_index];
|
|
+ struct curl_slist *field_cursor;
|
|
+ int field_count, field_index;
|
|
+ PyObject *cert;
|
|
+
|
|
+ field_count = 0;
|
|
+ field_cursor = fields;
|
|
+ while (field_cursor != NULL) {
|
|
+ field_cursor = field_cursor->next;
|
|
+ field_count ++;
|
|
+ }
|
|
+
|
|
+
|
|
+ cert = PyTuple_New((Py_ssize_t)field_count);
|
|
+ if (!cert)
|
|
+ goto error;
|
|
+ PyList_SetItem(certs, cert_index, cert); /* Eats the ref from New() */
|
|
+
|
|
+ for(field_index = 0, field_cursor = fields;
|
|
+ field_cursor != NULL;
|
|
+ field_index ++, field_cursor = field_cursor->next) {
|
|
+ const char *field = field_cursor->data;
|
|
+ PyObject *field_tuple;
|
|
+
|
|
+ if (!field) {
|
|
+ field_tuple = Py_None; Py_INCREF(field_tuple);
|
|
+ } else {
|
|
+ const char *sep = strchr(field, ':');
|
|
+ if (!sep) {
|
|
+ field_tuple = PyString_FromString(field);
|
|
+ } else {
|
|
+ field_tuple = Py_BuildValue("s#s", field, (int)(sep - field), sep+1);
|
|
+ }
|
|
+ if (!field_tuple)
|
|
+ goto error;
|
|
+ }
|
|
+ PyTuple_SET_ITEM(cert, field_index, field_tuple); /* Eats the ref */
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return certs;
|
|
+
|
|
+ error:
|
|
+ Py_XDECREF(certs);
|
|
+ return NULL;
|
|
+}
|
|
|
|
#ifdef WITH_THREAD
|
|
/*************************************************************************
|
|
@@ -1673,6 +1738,10 @@ util_curl_unsetopt(CurlObject *self, int option)
|
|
SETOPT((char *) 0);
|
|
break;
|
|
|
|
+ case CURLOPT_CERTINFO:
|
|
+ SETOPT((long) 0);
|
|
+ break;
|
|
+
|
|
/* info: we explicitly list unsupported options here */
|
|
case CURLOPT_COOKIEFILE:
|
|
default:
|
|
@@ -2394,6 +2463,18 @@ do_curl_getinfo(CurlObject *self, PyObject *args)
|
|
}
|
|
return convert_slist(slist, 1 | 2);
|
|
}
|
|
+
|
|
+ case CURLINFO_CERTINFO:
|
|
+ {
|
|
+ /* Return a list of lists of 2-tuples */
|
|
+ struct curl_certinfo *clist = NULL;
|
|
+ res = curl_easy_getinfo(self->handle, CURLINFO_CERTINFO, &clist);
|
|
+ if (res != CURLE_OK) {
|
|
+ CURLERROR_RETVAL();
|
|
+ } else {
|
|
+ return convert_certinfo(clist);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
/* Got wrong option on the method call */
|
|
@@ -3916,6 +3997,7 @@ initpycurl(void)
|
|
#ifdef HAVE_CURLOPT_RESOLVE
|
|
insint_c(d, "RESOLVE", CURLOPT_RESOLVE);
|
|
#endif
|
|
+ insint_c(d, "OPT_CERTINFO", CURLOPT_CERTINFO);
|
|
|
|
insint_c(d, "M_TIMERFUNCTION", CURLMOPT_TIMERFUNCTION);
|
|
insint_c(d, "M_SOCKETFUNCTION", CURLMOPT_SOCKETFUNCTION);
|
|
@@ -3993,6 +4075,7 @@ initpycurl(void)
|
|
insint_c(d, "INFO_COOKIELIST", CURLINFO_COOKIELIST);
|
|
insint_c(d, "LASTSOCKET", CURLINFO_LASTSOCKET);
|
|
insint_c(d, "FTP_ENTRY_PATH", CURLINFO_FTP_ENTRY_PATH);
|
|
+ insint_c(d, "INFO_CERTINFO", CURLINFO_CERTINFO);
|
|
|
|
/* options for global_init() */
|
|
insint(d, "GLOBAL_SSL", CURL_GLOBAL_SSL);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From aa82321393ebc813d326cb305a1e2f73bbe45abe Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 30 May 2013 14:42:38 -0400
|
|
Subject: [PATCH 143/149] Conditional compilation for CERTINFO bits
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 11 +++++++++++
|
|
1 files changed, 11 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index 5da354d..c0fec4b 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -66,6 +66,7 @@
|
|
LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH >= 1
|
|
#define HAVE_CURLOPT_USERNAME
|
|
#define HAVE_CURLOPT_PROXYUSERNAME
|
|
+#define HAVE_CURLOPT_CERTINFO
|
|
#endif
|
|
|
|
#if LIBCURL_VERSION_NUM >= 0x071503 /* check for 7.21.3 or greater */
|
|
@@ -297,6 +298,7 @@ error:
|
|
return NULL;
|
|
}
|
|
|
|
+#ifdef HAVE_CURLOPT_CERTINFO
|
|
/* Convert a struct curl_certinfo into a Python data structure.
|
|
* In case of error return NULL with an exception set.
|
|
*/
|
|
@@ -362,6 +364,7 @@ static PyObject *convert_certinfo(struct curl_certinfo *cinfo)
|
|
Py_XDECREF(certs);
|
|
return NULL;
|
|
}
|
|
+#endif
|
|
|
|
#ifdef WITH_THREAD
|
|
/*************************************************************************
|
|
@@ -1738,9 +1741,11 @@ util_curl_unsetopt(CurlObject *self, int option)
|
|
SETOPT((char *) 0);
|
|
break;
|
|
|
|
+#ifdef HAVE_CURLOPT_CERTINFO
|
|
case CURLOPT_CERTINFO:
|
|
SETOPT((long) 0);
|
|
break;
|
|
+#endif
|
|
|
|
/* info: we explicitly list unsupported options here */
|
|
case CURLOPT_COOKIEFILE:
|
|
@@ -2464,6 +2469,7 @@ do_curl_getinfo(CurlObject *self, PyObject *args)
|
|
return convert_slist(slist, 1 | 2);
|
|
}
|
|
|
|
+#ifdef HAVE_CURLOPT_CERTINFO
|
|
case CURLINFO_CERTINFO:
|
|
{
|
|
/* Return a list of lists of 2-tuples */
|
|
@@ -2476,6 +2482,7 @@ do_curl_getinfo(CurlObject *self, PyObject *args)
|
|
}
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
/* Got wrong option on the method call */
|
|
PyErr_SetString(PyExc_ValueError, "invalid argument to getinfo");
|
|
@@ -3997,7 +4004,9 @@ initpycurl(void)
|
|
#ifdef HAVE_CURLOPT_RESOLVE
|
|
insint_c(d, "RESOLVE", CURLOPT_RESOLVE);
|
|
#endif
|
|
+#ifdef HAVE_CURLOPT_CERTINFO
|
|
insint_c(d, "OPT_CERTINFO", CURLOPT_CERTINFO);
|
|
+#endif
|
|
|
|
insint_c(d, "M_TIMERFUNCTION", CURLMOPT_TIMERFUNCTION);
|
|
insint_c(d, "M_SOCKETFUNCTION", CURLMOPT_SOCKETFUNCTION);
|
|
@@ -4075,7 +4084,9 @@ initpycurl(void)
|
|
insint_c(d, "INFO_COOKIELIST", CURLINFO_COOKIELIST);
|
|
insint_c(d, "LASTSOCKET", CURLINFO_LASTSOCKET);
|
|
insint_c(d, "FTP_ENTRY_PATH", CURLINFO_FTP_ENTRY_PATH);
|
|
+#ifdef HAVE_CURLOPT_CERTINFO
|
|
insint_c(d, "INFO_CERTINFO", CURLINFO_CERTINFO);
|
|
+#endif
|
|
|
|
/* options for global_init() */
|
|
insint(d, "GLOBAL_SSL", CURL_GLOBAL_SSL);
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 68713450eef4fd4252babafefe24d42faebc6de9 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 30 May 2013 14:49:44 -0400
|
|
Subject: [PATCH 144/149] Use an ordinary DECREF
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
src/pycurl.c | 2 +-
|
|
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/src/pycurl.c b/src/pycurl.c
|
|
index c0fec4b..c8b8402 100644
|
|
--- a/src/pycurl.c
|
|
+++ b/src/pycurl.c
|
|
@@ -361,7 +361,7 @@ static PyObject *convert_certinfo(struct curl_certinfo *cinfo)
|
|
return certs;
|
|
|
|
error:
|
|
- Py_XDECREF(certs);
|
|
+ Py_DECREF(certs);
|
|
return NULL;
|
|
}
|
|
#endif
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 53999f0ca88f6a71ff0b9331ce9da89a5f07fb0f Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Thu, 30 May 2013 15:35:31 -0400
|
|
Subject: [PATCH 145/149] SSL certinfo test using github
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/certinfo_test.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 52 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/certinfo_test.py
|
|
|
|
diff --git a/tests/certinfo_test.py b/tests/certinfo_test.py
|
|
new file mode 100644
|
|
index 0000000..25c05af
|
|
--- /dev/null
|
|
+++ b/tests/certinfo_test.py
|
|
@@ -0,0 +1,52 @@
|
|
+#! /usr/bin/env python
|
|
+# -*- coding: iso-8859-1 -*-
|
|
+# vi:ts=4:et
|
|
+
|
|
+import pycurl
|
|
+import unittest
|
|
+import nose.plugins.skip
|
|
+
|
|
+from . import util
|
|
+
|
|
+class CertinfoTest(unittest.TestCase):
|
|
+ def setUp(self):
|
|
+ self.curl = pycurl.Curl()
|
|
+
|
|
+ def tearDown(self):
|
|
+ self.curl.close()
|
|
+
|
|
+ def test_certinfo_option(self):
|
|
+ # CURLOPT_CERTINFO was introduced in libcurl-7.19.1
|
|
+ if util.pycurl_version_less_than(7, 19, 1):
|
|
+ raise nose.plugins.skip.SkipTest('libcurl < 7.19.1')
|
|
+
|
|
+ assert hasattr(pycurl, 'OPT_CERTINFO')
|
|
+
|
|
+ def test_request_without_certinfo(self):
|
|
+ # CURLOPT_CERTINFO was introduced in libcurl-7.19.1
|
|
+ if util.pycurl_version_less_than(7, 19, 1):
|
|
+ raise nose.plugins.skip.SkipTest('libcurl < 7.19.1')
|
|
+
|
|
+ self.curl.setopt(pycurl.URL, 'https://github.com/')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.perform()
|
|
+ assert 'GitHub' in sio.getvalue()
|
|
+
|
|
+ certinfo = self.curl.getinfo(pycurl.INFO_CERTINFO)
|
|
+ self.assertEqual([], certinfo)
|
|
+
|
|
+ def test_request_with_certinfo(self):
|
|
+ # CURLOPT_CERTINFO was introduced in libcurl-7.19.1
|
|
+ if util.pycurl_version_less_than(7, 19, 1):
|
|
+ raise nose.plugins.skip.SkipTest('libcurl < 7.19.1')
|
|
+
|
|
+ self.curl.setopt(pycurl.URL, 'https://github.com/')
|
|
+ sio = util.StringIO()
|
|
+ self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ self.curl.setopt(pycurl.OPT_CERTINFO, 1)
|
|
+ self.curl.perform()
|
|
+ assert 'GitHub' in sio.getvalue()
|
|
+
|
|
+ certinfo = self.curl.getinfo(pycurl.INFO_CERTINFO)
|
|
+ assert len(certinfo) > 0
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 6ca51826965392ed3ac2338b5da7dac5215bd840 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 23 Jul 2013 20:10:47 -0400
|
|
Subject: [PATCH 146/149] Self signed certificate for ssl tests
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/certs/server.crt | 14 ++++++++++++++
|
|
tests/certs/server.key | 15 +++++++++++++++
|
|
2 files changed, 29 insertions(+), 0 deletions(-)
|
|
create mode 100644 tests/certs/server.crt
|
|
create mode 100644 tests/certs/server.key
|
|
|
|
diff --git a/tests/certs/server.crt b/tests/certs/server.crt
|
|
new file mode 100644
|
|
index 0000000..4a8decc
|
|
--- /dev/null
|
|
+++ b/tests/certs/server.crt
|
|
@@ -0,0 +1,14 @@
|
|
+-----BEGIN CERTIFICATE-----
|
|
+MIICJTCCAY4CCQDfQAHGuFkN2zANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJB
|
|
+VTETMBEGA1UECBMKU29tZS1TdGF0ZTEaMBgGA1UEChMRcHljdXJsIHRlc3Qgc3Vp
|
|
+dGUxFzAVBgNVBAMTDmxvY2FsaG9zdDo4MzgzMB4XDTEzMDcyNDAwMDgxNVoXDTE0
|
|
+MDcyNDAwMDgxNVowVzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx
|
|
+GjAYBgNVBAoTEXB5Y3VybCB0ZXN0IHN1aXRlMRcwFQYDVQQDEw5sb2NhbGhvc3Q6
|
|
+ODM4MzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxE0+59Kf2z9ccZyUAuKG
|
|
+QpkQaXtEJC13exY4SWIfr78FfCStdqpZdfmm66djFENhmaAZYGsPHGXrEIHQqja2
|
|
+7KYkHo4cXLxksR4Db01yPMtMU9xHzg37OTIS2lGRmMxLduKc5XKsxA98PV/D1k4k
|
|
+sqLcLDH//YdLR0iYUYLOIgMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAppFdMNMHe
|
|
+68uQA1y2xAYW7faUH8/g+XAuH9WjLL2QfWGXgWey/pwofsrTO2Hl+D9y8Rey4eJ/
|
|
+BDv3OV2cBWBYBOxZv/kqyDHQc38tho9gdaPQnD4ttFk2TSgaOs1W39pGY1On0Ejd
|
|
+O6CXEGV7p8C613AgEkbdudnn+ChvyH/Shw==
|
|
+-----END CERTIFICATE-----
|
|
diff --git a/tests/certs/server.key b/tests/certs/server.key
|
|
new file mode 100644
|
|
index 0000000..5bdbbf9
|
|
--- /dev/null
|
|
+++ b/tests/certs/server.key
|
|
@@ -0,0 +1,15 @@
|
|
+-----BEGIN RSA PRIVATE KEY-----
|
|
+MIICXAIBAAKBgQDETT7n0p/bP1xxnJQC4oZCmRBpe0QkLXd7FjhJYh+vvwV8JK12
|
|
+qll1+abrp2MUQ2GZoBlgaw8cZesQgdCqNrbspiQejhxcvGSxHgNvTXI8y0xT3EfO
|
|
+Dfs5MhLaUZGYzEt24pzlcqzED3w9X8PWTiSyotwsMf/9h0tHSJhRgs4iAwIDAQAB
|
|
+AoGAMLNFTvgnJpqikaEZ61lNm8ojkze8oQkSolvR3QrV96D5eGIVEuKSTT2Blucx
|
|
+In7RAO8CPLRyzEXQuoiqPwBSAxY2Xswd+zcAgN2Zi8uqWTmPNsW6451BJRemgLjK
|
|
+OxLxCdVTOTxHfttj/CnwYQ6zn55oyZJGGmaVGykbvH/AgukCQQD3HfhOPExsI/6X
|
|
+Bp7CeZOhmM+LBOQGQGDjRnBdRp0s3HiUfaDxU2mbEafGPI2OyuzpYAqxHVTJLai6
|
|
+CQlJGuQXAkEAy1upObz2bcN2dUCHNufk2qdfRSCRkmKemuqznwCW3fSoRKB+qOu3
|
|
+xyTLEkTvLBNnAFjoyd6B75QzL/7//qvo9QJAE0xV3dY7qZ5N/YFY2Jsh+layroqd
|
|
+PBe++UDA+afQEnbNO9trvCzlbGS+k26bJ3GVeswzSY2e128nZA/cl8bv1QJAfTEO
|
|
+uybjpqtAj+qL03drYljLw+jK9Y2VCtYWgnqAZmAp/yW3FBMZbpXuFm8ttrqzHHmf
|
|
+xjcfUvivkoqv2n7GyQJBAKxbBVx/LQiSVpOTnXTEA1NJF8NS2NCF+3sm3kGhFKql
|
|
+Hi/cCAFrhBl9MoPJF/6noukfIkq0SzjkWrYIcoBDoVg=
|
|
+-----END RSA PRIVATE KEY-----
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 2bc1535519faf3e574bac514b634d29ed7e28c20 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Sat, 1 Jun 2013 05:23:41 -0400
|
|
Subject: [PATCH 147/149] Support for testing against a local ssl server
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/runwsgi.py | 34 +++++++++++++++++++++++++++++-----
|
|
1 files changed, 29 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/tests/runwsgi.py b/tests/runwsgi.py
|
|
index 114ce42..c9bc236 100644
|
|
--- a/tests/runwsgi.py
|
|
+++ b/tests/runwsgi.py
|
|
@@ -4,6 +4,7 @@ import sys
|
|
import bottle
|
|
import threading
|
|
import socket
|
|
+import os.path
|
|
import time as _time
|
|
|
|
try:
|
|
@@ -37,6 +38,21 @@ class Server(bottle.WSGIRefServer):
|
|
else:
|
|
self.srv.serve_forever(poll_interval=0.1)
|
|
|
|
+class SslServer(bottle.CherryPyServer):
|
|
+ def run(self, handler):
|
|
+ import cherrypy.wsgiserver, cherrypy.wsgiserver.ssl_builtin
|
|
+ server = cherrypy.wsgiserver.CherryPyWSGIServer((self.host, self.port), handler)
|
|
+ cert_dir = os.path.join(os.path.dirname(__file__), 'certs')
|
|
+ ssl_adapter = cherrypy.wsgiserver.ssl_builtin.BuiltinSSLAdapter(
|
|
+ os.path.join(cert_dir, 'server.crt'),
|
|
+ os.path.join(cert_dir, 'server.key'),
|
|
+ )
|
|
+ server.ssl_adapter = ssl_adapter
|
|
+ try:
|
|
+ server.start()
|
|
+ finally:
|
|
+ server.stop()
|
|
+
|
|
def wait_for_network_service(netloc, check_interval, num_attempts):
|
|
ok = False
|
|
for i in range(num_attempts):
|
|
@@ -51,8 +67,8 @@ def wait_for_network_service(netloc, check_interval, num_attempts):
|
|
break
|
|
return ok
|
|
|
|
-def start_bottle_server(app, port, **kwargs):
|
|
- server_thread = ServerThread(app, port, kwargs)
|
|
+def start_bottle_server(app, port, server, **kwargs):
|
|
+ server_thread = ServerThread(app, port, server, kwargs)
|
|
server_thread.daemon = True
|
|
server_thread.start()
|
|
|
|
@@ -64,12 +80,12 @@ def start_bottle_server(app, port, **kwargs):
|
|
return server_thread.server
|
|
|
|
class ServerThread(threading.Thread):
|
|
- def __init__(self, app, port, server_kwargs):
|
|
+ def __init__(self, app, port, server, server_kwargs):
|
|
threading.Thread.__init__(self)
|
|
self.app = app
|
|
self.port = port
|
|
self.server_kwargs = server_kwargs
|
|
- self.server = Server(host='localhost', port=self.port, **self.server_kwargs)
|
|
+ self.server = server(host='localhost', port=self.port, **self.server_kwargs)
|
|
|
|
def run(self):
|
|
bottle.run(self.app, server=self.server, quiet=True)
|
|
@@ -104,7 +120,15 @@ def app_runner_setup(*specs):
|
|
if port in started_servers:
|
|
assert started_servers[port] == (app, kwargs)
|
|
else:
|
|
- self.servers.append(start_bottle_server(app, port, **kwargs))
|
|
+ server = Server
|
|
+ if 'server' in kwargs:
|
|
+ server = kwargs['server']
|
|
+ del kwargs['server']
|
|
+ elif 'ssl' in kwargs:
|
|
+ if kwargs['ssl']:
|
|
+ server = SslServer
|
|
+ del kwargs['ssl']
|
|
+ self.servers.append(start_bottle_server(app, port, server, **kwargs))
|
|
started_servers[port] = (app, kwargs)
|
|
|
|
def teardown(self):
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From 1bae541fbeb5d7554c29d76f7e57dc3bc6cb4985 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Pudeyev <oleg@bsdpower.com>
|
|
Date: Tue, 23 Jul 2013 20:11:25 -0400
|
|
Subject: [PATCH 148/149] Test against a local ssl server
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
tests/certinfo_test.py | 26 +++++++++++++++++++++-----
|
|
1 files changed, 21 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/tests/certinfo_test.py b/tests/certinfo_test.py
|
|
index 25c05af..1473d39 100644
|
|
--- a/tests/certinfo_test.py
|
|
+++ b/tests/certinfo_test.py
|
|
@@ -6,8 +6,12 @@ import pycurl
|
|
import unittest
|
|
import nose.plugins.skip
|
|
|
|
+from . import app
|
|
+from . import runwsgi
|
|
from . import util
|
|
|
|
+setup_module, teardown_module = runwsgi.app_runner_setup((app.app, 8383, dict(ssl=True)))
|
|
+
|
|
class CertinfoTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.curl = pycurl.Curl()
|
|
@@ -27,11 +31,13 @@ class CertinfoTest(unittest.TestCase):
|
|
if util.pycurl_version_less_than(7, 19, 1):
|
|
raise nose.plugins.skip.SkipTest('libcurl < 7.19.1')
|
|
|
|
- self.curl.setopt(pycurl.URL, 'https://github.com/')
|
|
+ self.curl.setopt(pycurl.URL, 'https://localhost:8383/success')
|
|
sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
+ # self signed certificate
|
|
+ self.curl.setopt(pycurl.SSL_VERIFYPEER, 0)
|
|
self.curl.perform()
|
|
- assert 'GitHub' in sio.getvalue()
|
|
+ assert sio.getvalue() == 'success'
|
|
|
|
certinfo = self.curl.getinfo(pycurl.INFO_CERTINFO)
|
|
self.assertEqual([], certinfo)
|
|
@@ -41,12 +47,22 @@ class CertinfoTest(unittest.TestCase):
|
|
if util.pycurl_version_less_than(7, 19, 1):
|
|
raise nose.plugins.skip.SkipTest('libcurl < 7.19.1')
|
|
|
|
- self.curl.setopt(pycurl.URL, 'https://github.com/')
|
|
+ self.curl.setopt(pycurl.URL, 'https://localhost:8383/success')
|
|
sio = util.StringIO()
|
|
self.curl.setopt(pycurl.WRITEFUNCTION, sio.write)
|
|
self.curl.setopt(pycurl.OPT_CERTINFO, 1)
|
|
+ # self signed certificate
|
|
+ self.curl.setopt(pycurl.SSL_VERIFYPEER, 0)
|
|
self.curl.perform()
|
|
- assert 'GitHub' in sio.getvalue()
|
|
+ assert sio.getvalue() == 'success'
|
|
|
|
certinfo = self.curl.getinfo(pycurl.INFO_CERTINFO)
|
|
- assert len(certinfo) > 0
|
|
+ # self signed certificate, one certificate in chain
|
|
+ assert len(certinfo) == 1
|
|
+ certinfo = certinfo[0]
|
|
+ # convert to a dictionary
|
|
+ certinfo_dict = {}
|
|
+ for entry in certinfo:
|
|
+ certinfo_dict[entry[0]] = entry[1]
|
|
+ assert 'Subject' in certinfo_dict
|
|
+ assert 'pycurl test suite' in certinfo_dict['Subject']
|
|
--
|
|
1.7.1
|
|
|
|
|
|
From bb2b2e6f5a7dd7a343e2c1207ca152dbeb4cf14b Mon Sep 17 00:00:00 2001
|
|
From: Romulo A. Ceccon <romuloceccon@gmail.com>
|
|
Date: Fri, 26 Jul 2013 10:23:26 -0300
|
|
Subject: [PATCH 149/149] Added documentation for dependency on CherryPy
|
|
|
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
---
|
|
README.rst | 3 ++-
|
|
requirements-dev.txt | 1 +
|
|
2 files changed, 3 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/README.rst b/README.rst
|
|
index b416b97..e0641d0 100644
|
|
--- a/README.rst
|
|
+++ b/README.rst
|
|
@@ -56,7 +56,7 @@ PycURL comes with an automated test suite. To run the tests, execute::
|
|
|
|
make test
|
|
|
|
-The suite depends on packages `nose`_ and `bottle`_.
|
|
+The suite depends on packages `nose`_, `bottle`_ and `cherrypy`_.
|
|
|
|
Some tests use vsftpd configured to accept anonymous uploads. These tests
|
|
are not run by default. As configured, vsftpd will allow reads and writes to
|
|
@@ -71,6 +71,7 @@ vsftpd tests you must explicitly set PYCURL_VSFTPD_PATH variable like so::
|
|
|
|
.. _nose: https://nose.readthedocs.org/
|
|
.. _bottle: http://bottlepy.org/
|
|
+.. _cherrypy: http://www.cherrypy.org/
|
|
|
|
Contribute
|
|
----------
|
|
diff --git a/requirements-dev.txt b/requirements-dev.txt
|
|
index 36b0b24..ea11ac9 100644
|
|
--- a/requirements-dev.txt
|
|
+++ b/requirements-dev.txt
|
|
@@ -1,2 +1,3 @@
|
|
bottle
|
|
nose
|
|
+cherrypy
|
|
--
|
|
1.7.1
|
|
|