[Python-checkins] python/nondist/sandbox/itertools NEWS,NONE,1.1 itertools.c,1.7,1.8 libitertools.tex,1.7,1.8 test_itertools.py,1.5,1.6 todo.txt,1.8,1.9

rhettinger@users.sourceforge.net rhettinger@users.sourceforge.net
Mon, 27 Jan 2003 04:16:45 -0800


Update of /cvsroot/python/python/nondist/sandbox/itertools
In directory sc8-pr-cvs1:/tmp/cvs-serv26261

Modified Files:
	itertools.c libitertools.tex test_itertools.py todo.txt 
Added Files:
	NEWS 
Log Message:
Add dropwhile().

--- NEW FILE: NEWS ---
- Added an itertools module containing high speed looping constructs
  inspired by tools in Haskell and SML.

Index: itertools.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/itertools/itertools.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** itertools.c	27 Jan 2003 11:17:45 -0000	1.7
--- itertools.c	27 Jan 2003 12:16:42 -0000	1.8
***************
*** 2,5 ****
--- 2,150 ----
  #include "Python.h"
  
+ /* dropwhile object ************************************************************/
+ 
+ typedef struct {
+ 	PyObject_HEAD
+ 	PyObject *func;
+ 	PyObject *it;
+ 	long	 start;
+ } dropwhileobject;
+ 
+ PyTypeObject dropwhile_type;
+ 
+ static PyObject *
+ dropwhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ 	PyObject *func, *seq;
+ 	PyObject *it;
+ 	dropwhileobject *lz;
+ 
+ 	if (!PyArg_UnpackTuple(args, "dropwhile", 2, 2, &func, &seq))
+ 		return NULL;
+ 
+ 	/* Get iterator. */
+ 	it = PyObject_GetIter(seq);
+ 	if (it == NULL)
+ 		return NULL;
+ 
+ 	/* create dropwhileobject structure */
+ 	lz = (dropwhileobject *)type->tp_alloc(type, 0);
+ 	if (lz == NULL) {
+ 		Py_DECREF(it);
+ 		return NULL;
+ 	}
+ 	Py_INCREF(func);
+ 	lz->func = func;
+ 	lz->it = it;
+ 	lz->start = 0;
+ 
+ 	return (PyObject *)lz;
+ }
+ 
+ static void
+ dropwhile_dealloc(dropwhileobject *lz)
+ {
+ 	PyObject_GC_UnTrack(lz);
+ 	Py_XDECREF(lz->func);
+ 	Py_XDECREF(lz->it);
+ 	lz->ob_type->tp_free(lz);
+ }
+ 
+ static int
+ dropwhile_traverse(dropwhileobject *lz, visitproc visit, void *arg)
+ {
+ 	if (lz->it)
+ 		return visit(lz->it, arg);
+ 	return 0;
+ }
+ 
+ static PyObject *
+ dropwhile_next(dropwhileobject *lz)
+ {
+ 	PyObject *item, *good;
+ 	long ok;
+ 
+ 	for (;;) {
+ 		item = PyIter_Next(lz->it);
+ 		if (item == NULL)
+ 			return NULL;
+ 		if (lz->start == 1)
+ 			return item;
+ 
+ 		good = PyObject_CallFunctionObjArgs(lz->func, item, NULL);
+ 		if (good == NULL) {
+ 			printf("R");
+ 			Py_DECREF(item);
+ 			return NULL;
+ 		}
+ 		ok = PyObject_IsTrue(good);
+ 		Py_DECREF(good);
+ 		if (!ok) {
+ 			lz->start = 1;
+ 			return item;
+ 		}
+ 		Py_DECREF(item);
+ 	}
+ }
+ 
+ static PyObject *
+ dropwhile_getiter(PyObject *lz)
+ {
+ 	Py_INCREF(lz);
+ 	return lz;
+ }
+ 
+ PyDoc_STRVAR(dropwhile_doc,
+ "dropwhile(predicate, iterable) --> dropwhile object\n\
+ \n\
+ Drop items from the iterable while predicate(item) is true.\n\
+ Afterwards, return every element until the iterable is exhausted.");
+ 
+ PyTypeObject dropwhile_type = {
+ 	PyObject_HEAD_INIT(NULL)
+ 	0,				/* ob_size */
+ 	"itertools.dropwhile",		 /* tp_name */
+ 	sizeof(dropwhileobject),		 /* tp_basicsize */
+ 	0,				/* tp_itemsize */
+ 	/* methods */
+ 	(destructor)dropwhile_dealloc,	   /* tp_dealloc */
+ 	0,				/* tp_print */
+ 	0,				/* tp_getattr */
+ 	0,				/* tp_setattr */
+ 	0,				/* tp_compare */
+ 	0,				/* tp_repr */
+ 	0,				/* tp_as_number */
+ 	0,				/* tp_as_sequence */
+ 	0,				/* tp_as_mapping */
+ 	0,				/* tp_hash */
+ 	0,				/* tp_call */
+ 	0,				/* tp_str */
+ 	PyObject_GenericGetAttr,	/* tp_getattro */
+ 	0,				/* tp_setattro */
+ 	0,				/* tp_as_buffer */
+ 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ 		Py_TPFLAGS_BASETYPE,	/* tp_flags */
+ 	dropwhile_doc,			   /* tp_doc */
+ 	(traverseproc)dropwhile_traverse,    /* tp_traverse */
+ 	0,				/* tp_clear */
+ 	0,				/* tp_richcompare */
+ 	0,				/* tp_weaklistoffset */
+ 	(getiterfunc)dropwhile_getiter,	   /* tp_iter */
+ 	(iternextfunc)dropwhile_next,	   /* tp_iternext */
+ 	0,				/* tp_methods */
+ 	0,				/* tp_members */
+ 	0,				/* tp_getset */
+ 	0,				/* tp_base */
+ 	0,				/* tp_dict */
+ 	0,				/* tp_descr_get */
+ 	0,				/* tp_descr_set */
+ 	0,				/* tp_dictoffset */
+ 	0,				/* tp_init */
+ 	PyType_GenericAlloc,		/* tp_alloc */
+ 	dropwhile_new,			 /* tp_new */
+ 	PyObject_GC_Del,		/* tp_free */
+ };
+ 
+ 
  /* takewhile object ************************************************************/
  
***************
*** 1233,1243 ****
         same list each time but with updated contents\n\
  ifilter(pred, seq, invert=False) --> elements of seq where\n\
!        pred(elem) is True (or False invert is set)\n\
! islice(seq, start, stop, step) --> elements from\n\
         seq[start:stop:step]\n\
! imap(fun, p, q) --> fun(p0, q0), fun(p1, q1), ...\n\
  starmap(fun, s) --> fun(*s[0]), fun(*s[1]), ...\n\
  times(n) --> None, None, ... for n times.\n\
  takewhile(pred, seq) --> s[0], s[1], until pred fails\n\
  ");
  
--- 1378,1389 ----
         same list each time but with updated contents\n\
  ifilter(pred, seq, invert=False) --> elements of seq where\n\
!        pred(elem) is True (or False if invert is set)\n\
! islice(seq, [start,] stop [, step]) --> elements from\n\
         seq[start:stop:step]\n\
! imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
  starmap(fun, s) --> fun(*s[0]), fun(*s[1]), ...\n\
  times(n) --> None, None, ... for n times.\n\
  takewhile(pred, seq) --> s[0], s[1], until pred fails\n\
+ dropwhile(pred, seq) --> s[n], s[n+1], starting when pred fails\n\
  ");
  
***************
*** 1248,1251 ****
--- 1394,1402 ----
  	PyObject *m;
  	m = Py_InitModule3("itertools", NULL, module_doc);
+ 
+ 	PyModule_AddObject(m, "dropwhile", (PyObject *)&dropwhile_type);
+ 	if (PyType_Ready(&dropwhile_type) < 0)
+ 		return;
+ 	Py_INCREF(&dropwhile_type);
  
  	PyModule_AddObject(m, "takewhile", (PyObject *)&takewhile_type);

Index: libitertools.tex
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/itertools/libitertools.tex,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** libitertools.tex	27 Jan 2003 10:44:52 -0000	1.7
--- libitertools.tex	27 Jan 2003 12:16:42 -0000	1.8
***************
*** 74,83 ****
  \begin{seealso}
    \seetext{The Standard ML Basis Library,
! 	   \citetitle[http://www.standardml.org/Basis/]
! 	   {The Standard ML Basis Library}.}
  
    \seetext{Haskell, A Purely Functional Language,
             \citetitle[http://www.haskell.org/definition/]
! 	   {Definition of Haskell and the Standard Libraries}.}
  \end{seealso}
  
--- 74,83 ----
  \begin{seealso}
    \seetext{The Standard ML Basis Library,
!            \citetitle[http://www.standardml.org/Basis/]
!            {The Standard ML Basis Library}.}
  
    \seetext{Haskell, A Purely Functional Language,
             \citetitle[http://www.haskell.org/definition/]
!            {Definition of Haskell and the Standard Libraries}.}
  \end{seealso}
  
***************
*** 102,105 ****
--- 102,123 ----
  \end{funcdesc}
  
+ \begin{funcdesc}{dropwhile}{predicate, iterable}
+   Make an iterator that drops elements from the iterable as long as
+   the predicate is true; afterwards, returns every element.
+   Equivalent to:
+ 
+   \begin{verbatim}
+      def dropwhile(func, iterable, invert=False):
+          iterable = iter(iterable)
+          while True:
+              x = iterable.next()
+              if not predicate(x):
+                  yield x
+                  break
+          while True:
+              yield iterable.next()
+   \end{verbatim}
+ \end{funcdesc}
+ 
  \begin{funcdesc}{ifilter}{func, iterable \optional{, invert}}
    Make an iterator that filters elements from iterable returning only
***************
*** 200,203 ****
--- 218,237 ----
           while True:
               yield func(*iterable.next())
+   \end{verbatim}
+ \end{funcdesc}
+ 
+ \begin{funcdesc}{takewhile}{predicate, iterable}
+   Make an iterator that returns elements from the iterable as long as
+   the predicate is true.  Equivalent to:
+ 
+   \begin{verbatim}
+      def takewhile(func, iterable, invert=False):
+          iterable = iter(iterable)
+          while True:
+              x = iterable.next()
+              if predicate(x):
+                  yield x
+              else:
+                  break
    \end{verbatim}
  \end{funcdesc}

Index: test_itertools.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/itertools/test_itertools.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** test_itertools.py	27 Jan 2003 11:17:45 -0000	1.5
--- test_itertools.py	27 Jan 2003 12:16:42 -0000	1.6
***************
*** 75,82 ****
          self.assertEqual(list(takewhile(underten, data)), [1, 3, 5])
  
! ##    def test_dropwhile(self):
! ##        data = [1, 3, 5, 20, 2, 4, 6, 8]
! ##        underten = lambda x: x<10
! ##        self.assertEqual(list(takewhile(underten, data)), [20, 2, 4, 6, 8])     
  
  def test_main():
--- 75,82 ----
          self.assertEqual(list(takewhile(underten, data)), [1, 3, 5])
  
!     def test_dropwhile(self):
!         data = [1, 3, 5, 20, 2, 4, 6, 8]
!         underten = lambda x: x<10
!         self.assertEqual(list(dropwhile(underten, data)), [20, 2, 4, 6, 8])
  
  def test_main():

Index: todo.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/itertools/todo.txt,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** todo.txt	27 Jan 2003 11:17:45 -0000	1.8
--- todo.txt	27 Jan 2003 12:16:42 -0000	1.9
***************
*** 1,5 ****
  Add:
     iapply(func)  			?? what did this do in SML
-    dropwhile(pred, seqn)
     unzip(seqn)                          ?? does this make sense for iterators
     exists() and any()                   ?? these don't return iterators
--- 1,4 ----
***************
*** 16,19 ****
  
  Things that just bug me:
!     islice is supposed to looklike i-slice but can be read as is-lice
      
--- 15,18 ----
  
  Things that just bug me:
!     islice is supposed to sound like i-slice but can be read as is-lice