I try to move this to -dev as I hope there more people reading it who
are competent in internal working :). So please replay to -dev only.

-------------

The question is about use of generators in embedde v2.4 with asserts
enabled.

Can somebody explain, why the code in try2.c works with wrappers 2 and 3
but crashes on buggy exception for all others, that is pure generator
and wrappers 1,4,5 ?

In other words, what does [i in i for gen] do differently than other
ways of iterating over gen, which helps it to avoid the assert, and
also, how could I write something that is still a generator, but does
not trigger the assert.

While the right solution is to just fix python (which is done for v2.5)
we need a workaround for the following reason

We have added support for returning rows (as tuples and or dictionaries
or classes) and sets of boths scalars and rows to PostgreSQL's
pl/plpython embedded language, but have some objections to getting this
into distribution, because there is a bug in python 2.4 doing a wrong
assert and additional bug in how RedHat rpm build process which leaves
the buggy asserts in python.so.

So I hoped to write a simple wrapper class, but it only seems to work,
when the generator is turned into list, which is not a good solution as
it works directly against what generators are good for.

-- 
----------------
Hannu Krosing
Database Architect
Skype Technologies OÜ
Akadeemia tee 21 F, Tallinn, 12618, Estonia

Skype me:  callto:hkrosing
Get Skype for free:  http://www.skype.com

#include <Python.h>
#include <frameobject.h>

const char *py_source = 
    "def fn():\n"
    "    print 'one'\n"
    "    yield 1\n"
    "    print 'two'\n"
    "    yield 2\n"
;

const char *wrapper_source1 =
    "class gwrap:\n"
    "    def __init__(self,gen):\n"
    "        self.gen = gen\n"
    "    def __iter__(self):\n"
    "        return iter(self.gen)\n"
;

const char *wrapper_source2 =
    "def gwrap(gen):\n"
    "    return [i for i in gen]\n"
;

const char *wrapper_source3 =
    "def gwrap(gen):\n"
    "    return (x for x in [i for i in gen])\n"
;

const char *wrapper_source4 =
    "class gwrap:\n"
    "    def __init__(self,gen):\n"
    "        list = [i for i in gen]\n"
    "        self.gen = list.__iter__()\n"
    "    def __iter__(self):\n"
    "        return iter(self.gen)\n"
;

const char *wrapper_source5 =
    "def gwrap(gen):\n"
    "    return (i for i in gen)\n"
;



int main (int argc, char *argv[])
{
  Py_Initialize();

  PyObject *main_module = PyImport_AddModule("__main__");

  PyObject *globals = PyObject_GetAttrString(	main_module, "__dict__");

  // insert function code into interpreter
  PyObject *code = PyRun_String(py_source, Py_file_input, globals, NULL);
  Py_DECREF(code);

  // insert wrapper class into interpreter
  PyObject *code2 = PyRun_String(wrapper_source5, Py_file_input, globals, NULL);
  Py_DECREF(code2);

  // compile call to the function
  code = Py_CompileString("gwrap(fn())", "<string>", Py_eval_input);
//  code = Py_CompileString("fn()", "<string>", Py_eval_input);

  // do call
  PyObject *gen = PyEval_EvalCode((PyCodeObject *)code, globals, NULL);
  gen = PyObject_GetIter((PyObject *)gen);

  // iterate result
  PyObject *item;
  while ((item = PyIter_Next(gen))) {
      printf("> %ld\n", PyInt_AsLong(item));
      Py_DECREF(item);
  }

  Py_DECREF(gen);
  Py_DECREF(code);
  Py_DECREF(globals);

  Py_Finalize();
  return 0;
}
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to