# HG changeset patch
# User hodgestar
# Date 1395315888 0
# Node ID cddcb39ce5dd3a381180234c9995a3c9335a911c
# Parent 9da42eed139b5c5c12b4d186baf2a0553ef7bf8d
Merge r1266 from trunk (support for iterators in _speedups.Markup.join).
diff --git a/genshi/_speedups.c b/genshi/_speedups.c
--- a/genshi/_speedups.c
+++ b/genshi/_speedups.c
@@ -242,39 +242,35 @@
Markup_join(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"seq", "escape_quotes", 0};
- PyObject *seq = NULL, *seq2, *tmp, *tmp2;
+ PyObject *seq = NULL, *seq2, *it, *tmp, *tmp2;
char quotes = 1;
- Py_ssize_t n;
- int i;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|b", kwlist, &seq, "es)) {
return NULL;
}
- if (!PySequence_Check(seq)) {
+ it = PyObject_GetIter(seq);
+ if (it == NULL)
return NULL;
- }
- n = PySequence_Size(seq);
- if (n < 0) {
+ seq2 = PyList_New(0);
+ if (seq2 == NULL) {
+ Py_DECREF(it);
return NULL;
}
- seq2 = PyTuple_New(n);
- if (seq2 == NULL) {
- return NULL;
- }
- for (i = 0; i < n; i++) {
- tmp = PySequence_GetItem(seq, i);
- if (tmp == NULL) {
- Py_DECREF(seq2);
- return NULL;
- }
+ while ((tmp = PyIter_Next(it))) {
tmp2 = escape(tmp, quotes);
if (tmp2 == NULL) {
Py_DECREF(seq2);
+ Py_DECREF(it);
return NULL;
}
- PyTuple_SET_ITEM(seq2, i, tmp2);
+ PyList_Append(seq2, tmp2);
Py_DECREF(tmp);
}
+ Py_DECREF(it);
+ if (PyErr_Occurred()) {
+ Py_DECREF(seq2);
+ return NULL;
+ }
tmp = PyUnicode_Join(self, seq2);
Py_DECREF(seq2);
if (tmp == NULL)
diff --git a/genshi/tests/core.py b/genshi/tests/core.py
--- a/genshi/tests/core.py
+++ b/genshi/tests/core.py
@@ -139,6 +139,11 @@
assert type(markup) is Markup
self.assertEquals('foo
<bar />
', markup)
+ def test_join_over_iter(self):
+ items = ['foo', '', Markup('')]
+ markup = Markup('
').join(i for i in items)
+ self.assertEquals('foo
<bar />
', markup)
+
def test_stripentities_all(self):
markup = Markup('& j').stripentities()
assert type(markup) is Markup