[Patches] UPDATE: array.{pop,extend} [array.{count,index,remove}]

Peter Schneider-Kamp peter@schneider-kamp.de
Mon, 12 Jun 2000 13:45:32 +0200


This is a multi-part message in MIME format.
--------------A1BB794F76124C6DB9BD056D
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Guido van Rossum wrote:
> 
> My suggestion would be to add pop() and extend() but leave the slow
> ones (count, index, remove) out.

Now the patch adds pop() and extend(), the other three replace
the non-working versions which somebody (Tim?) added at some time
(long ago?), but are still #if 0..#endif'ed.

Documentation and tests for pop() and extend() are also added.

Nevertheless I don't see the harm of having those "slow" versions.
If somebody really should need them, they are more convenient and
probably also faster than equivalent Python code.

Peter

patch attached as plaintext context diff
--
I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.
--
Peter Schneider-Kamp          ++47-7388-7331
Herman Krags veg 51-11        mailto:peter@schneider-kamp.de
N-7050 Trondheim              http://schneider-kamp.de
--------------A1BB794F76124C6DB9BD056D
Content-Type: text/plain; charset=us-ascii;
 name="array.pop-extend.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="array.pop-extend.patch"

diff -c -b --recursive python/dist/src/Doc/lib/libarray.tex python-mod/dist/src/Doc/lib/libarray.tex
*** python/dist/src/Doc/lib/libarray.tex	Mon Apr  3 22:13:52 2000
--- python-mod/dist/src/Doc/lib/libarray.tex	Mon Jun 12 13:13:39 2000
***************
*** 83,88 ****
--- 83,92 ----
  data from a file written on a machine with a different byte order.
  \end{methoddesc}
  
+ \begin{methoddesc}[array]{extend}{a}
+ Append array items from \var{a} to the end of the array.
+ \end{methoddesc}
+ 
  \begin{methoddesc}[array]{fromfile}{f, n}
  Read \var{n} items (as machine values) from the file object \var{f}
  and append them to the end of the array.  If less than \var{n} items
***************
*** 107,112 ****
--- 111,122 ----
  \begin{methoddesc}[array]{insert}{i, x}
  Insert a new item with value \var{x} in the array before position
  \var{i}.
+ \end{methoddesc}
+ 
+ \begin{methoddesc}[array]{pop}{\optional{i}}
+ Removes the item with the index \var{i} from the array and returns
+ it. The optional argument defaults to \code{-1}, so that by default
+ the last item is removed and returned. 
  \end{methoddesc}
  
  \begin{methoddesc}[array]{read}{f, n}
diff -c -b --recursive python/dist/src/Doc/lib/libstdtypes.tex python-mod/dist/src/Doc/lib/libstdtypes.tex
*** python/dist/src/Doc/lib/libstdtypes.tex	Mon Apr  3 22:13:54 2000
--- python-mod/dist/src/Doc/lib/libstdtypes.tex	Mon Jun 12 11:34:16 2000
***************
*** 506,513 ****
  \item[(3)] Raises \exception{ValueError} when \var{x} is not found in
    \var{s}.
  
! \item[(4)] The \method{pop()} method is experimental and not supported 
!   by other mutable sequence types than lists.  The optional argument
    \var{i} defaults to \code{-1}, so that by default the last item is
    removed and returned.
  
--- 506,513 ----
  \item[(3)] Raises \exception{ValueError} when \var{x} is not found in
    \var{s}.
  
! \item[(4)] The \method{pop()} method is experimental and at the moment
!   only supported by the list and array types.  The optional argument
    \var{i} defaults to \code{-1}, so that by default the last item is
    removed and returned.
  
diff -c -b --recursive python/dist/src/Lib/test/test_array.py python-mod/dist/src/Lib/test/test_array.py
*** python/dist/src/Lib/test/test_array.py	Thu Jul 16 17:31:43 1998
--- python-mod/dist/src/Lib/test/test_array.py	Mon Jun 12 13:20:51 2000
***************
*** 67,72 ****
--- 67,86 ----
              a[1:-1] = a
              if a != array.array(type, "aabcdee"):
                  raise TestFailed, "array(%s) self-slice-assign (cntr)" % `type`
+             if a.pop(0) != "a":
+             	raise TestFailed, "array(%s) pop-test" % `type`
+             if a.pop(1) != "b":
+             	raise TestFailed, "array(%s) pop-test" % `type`
+             a.extend(array.array(type, "xyz"))
+             if a != array.array(type, "acdeexyz"):
+                 raise TestFailed, "array(%s) extend-test" % `type`
+             a.pop()
+             a.pop()
+             a.pop()
+             a.pop()
+             a.pop()
+             if a != array.array(type, "acd"):
+             	raise TestFailed, "array(%s) pop-test" % `type`
          else:
              a = array.array(type, [1, 2, 3, 4, 5])
              a[:-1] = a
***************
*** 80,85 ****
--- 94,113 ----
              a[1:-1] = a
              if a != array.array(type, [1, 1, 2, 3, 4, 5, 5]):
                  raise TestFailed, "array(%s) self-slice-assign (cntr)" % `type`
+             if a.pop(0) != 1:
+             	raise TestFailed, "array(%s) pop-test" % `type`
+             if a.pop(1) != 2:
+             	raise TestFailed, "array(%s) pop-test" % `type`
+             a.extend(array.array(type, [7, 8, 9]))
+             if a != array.array(type, [1, 3, 4, 5, 5, 7, 8, 9]):
+                 raise TestFailed, "array(%s) extend-test" % `type`
+             a.pop()
+             a.pop()
+             a.pop()
+             a.pop()
+             a.pop()
+             if a != array.array(type, [1, 3, 4]):
+             	raise TestFailed, "array(%s) pop-test" % `type`
  
  
  main()
diff -c -b --recursive python/dist/src/Modules/arraymodule.c python-mod/dist/src/Modules/arraymodule.c
*** python/dist/src/Modules/arraymodule.c	Thu Jun  1 04:02:46 2000
--- python-mod/dist/src/Modules/arraymodule.c	Mon Jun 12 13:17:35 2000
***************
*** 703,708 ****
--- 703,785 ----
  }
  
  static PyObject *
+ array_pop(self, args)
+ 	arrayobject *self;
+ 	PyObject *args;
+ {
+ 	int i = -1;
+ 	PyObject *v;
+ 	if (!PyArg_ParseTuple(args, "|i:pop", &i))
+ 		return NULL;
+ 	if (self->ob_size == 0) {
+ 		/* Special-case most common failure cause */
+ 		PyErr_SetString(PyExc_IndexError, "pop from empty array");
+ 		return NULL;
+ 	}
+ 	if (i < 0)
+ 		i += self->ob_size;
+ 	if (i < 0 || i >= self->ob_size) {
+ 		PyErr_SetString(PyExc_IndexError, "pop index out of range");
+ 		return NULL;
+ 	}
+ 	v = getarrayitem((PyObject *)self,i);
+ 	Py_INCREF(v);
+ 	if (array_ass_slice(self, i, i+1, (PyObject *)NULL) != 0) {
+ 		Py_DECREF(v);
+ 		return NULL;
+ 	}
+ 	return v;
+ }
+ 
+ static char pop_doc [] =
+ "pop ([i])\n\
+ \n\
+ Return the i-th element and delete it from the array. i defaults to -1.";
+ 
+ static PyObject *
+ array_extend(self, args)
+ 	arrayobject *self;
+ 	PyObject *args;
+ {
+ 	int size;
+         PyObject    *bb;
+         arrayobject *np;
+         
+ 	if (!PyArg_ParseTuple(args, "O:extend", &bb))
+             return NULL;
+         
+ 	if (!is_arrayobject(bb)) {
+ 		PyErr_Format(PyExc_TypeError,
+ 		     "can only append array (not \"%.200s\") to array",
+ 			     bb->ob_type->tp_name);
+ 		return NULL;
+ 	}
+ #define b ((arrayobject *)bb)
+ 	if (self->ob_descr != b->ob_descr) {
+ 		PyErr_BadArgument();
+ 		return NULL;
+ 	}
+ 	size = self->ob_size + b->ob_size;
+         PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize);
+         if (self->ob_item == NULL) {
+                 PyObject_Del(self);
+                 return PyErr_NoMemory();
+         }
+ 	memcpy(self->ob_item + self->ob_size*self->ob_descr->itemsize,
+                b->ob_item, b->ob_size*b->ob_descr->itemsize);
+         self->ob_size = size;
+         Py_INCREF(Py_None);
+ 	return Py_None;
+ #undef b
+ }
+ 
+ static char extend_doc [] =
+ "extend(array)\n\
+ \n\
+ Append array items to the end of the array.";
+ 
+ 
+ static PyObject *
  array_insert(self, args)
  	arrayobject *self;
  	PyObject *args;
***************
*** 850,900 ****
  \n\
  Reverse the order of the items in the array.";
  
! /* The following routines were adapted from listobject.c but not converted.
!    To make them work you will have to work! */
  
  #if 0
  static PyObject *
! array_index(self, args)
  	arrayobject *self;
  	PyObject *args;
  {
  	int i;
  	
! 	if (args == NULL) {
! 		PyErr_BadArgument();
  		return NULL;
- 	}
  	for (i = 0; i < self->ob_size; i++) {
! 		if (PyObject_Compare(self->ob_item[i], args) == 0)
! 			return PyInt_FromLong((long)i);
! 		/* XXX PyErr_Occurred */
! 	}
! 	PyErr_SetString(PyExc_ValueError, "array.index(x): x not in array");
  	return NULL;
  }
  #endif
  
  #if 0
  static PyObject *
! array_count(self, args)
  	arrayobject *self;
  	PyObject *args;
  {
- 	int count = 0;
  	int i;
  	
! 	if (args == NULL) {
! 		PyErr_BadArgument();
  		return NULL;
- 	}
  	for (i = 0; i < self->ob_size; i++) {
! 		if (PyObject_Compare(self->ob_item[i], args) == 0)
! 			count++;
! 		/* XXX PyErr_Occurred */
  	}
! 	return PyInt_FromLong((long)count);
  }
  #endif
  
  #if 0
--- 927,988 ----
  \n\
  Reverse the order of the items in the array.";
  
! /* The following routines were adapted from listobject.c, but are not
!    included because they are considered too slow. To use them you
!    additionally have to uncomment the method hookups. */
  
  #if 0
  static PyObject *
! array_count(self, args)
  	arrayobject *self;
  	PyObject *args;
  {
+ 	int count = 0;
  	int i;
+ 	PyObject *v;
  
! 	if (!PyArg_Parse(args, "O", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
! 		if (PyObject_Compare(getarrayitem((PyObject *)self,i), v) == 0)
! 			count++;
! 		if (PyErr_Occurred())
  			return NULL;
+ 	}
+ 	return PyInt_FromLong((long)count);
  }
+ 
+ static char count_doc [] =
+ "count (x)\n\
+ \n\
+ Return number of occurences of x in the array.";
  #endif
  
  #if 0
  static PyObject *
! array_index(self, args)
  	arrayobject *self;
          PyObject *args;
  {
  	int i;
+ 	PyObject *v;
  
! 	if (!PyArg_Parse(args, "O", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
! 		if (PyObject_Compare(getarrayitem((PyObject *)self,i), v) == 0)
! 			return PyInt_FromLong((long)i);
! 		if (PyErr_Occurred())
! 			return NULL;
  	}
! 	PyErr_SetString(PyExc_ValueError, "array.index(x): x not in list");
! 	return NULL;
  }
+ 
+ static char index_doc [] =
+ "index (x)\n\
+ \n\
+ Return index of first occurence of x in the array.";
  #endif
  
  #if 0
***************
*** 904,927 ****
  	PyObject *args;
  {
  	int i;
  	
! 	if (args == NULL) {
! 		PyErr_BadArgument();
  		return NULL;
- 	}
  	for (i = 0; i < self->ob_size; i++) {
! 		if (PyObject_Compare(self->ob_item[i], args) == 0) {
  			if (array_ass_slice(self, i, i+1,
  					    (PyObject *)NULL) != 0)
  				return NULL;
  			Py_INCREF(Py_None);
  			return Py_None;
  		}
! 		/* XXX PyErr_Occurred */
  	}
! 	PyErr_SetString(PyExc_ValueError, "array.remove(x): x not in array");
  	return NULL;
  }
  #endif
  
  static PyObject *
--- 992,1020 ----
  	PyObject *args;
  {
  	int i;
+ 	PyObject *v;
  
! 	if (!PyArg_Parse(args, "O", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
! 		if (PyObject_Compare(getarrayitem((PyObject *)self,i), v) == 0) {
  			if (array_ass_slice(self, i, i+1,
  					   (PyObject *)NULL) != 0)
  				return NULL;
  			Py_INCREF(Py_None);
  			return Py_None;
  		}
! 		if (PyErr_Occurred())
! 			return NULL;
  	}
! 	PyErr_SetString(PyExc_ValueError, "array.remove(x): x not in list");
  	return NULL;
  }
+ 
+ static char remove_doc [] =
+ "remove (x)\n\
+ \n\
+ Remove the first occurence of x in the array.";
  #endif
  
  static PyObject *
***************
*** 1147,1162 ****
  	{"buffer_info", (PyCFunction)array_buffer_info, 0, buffer_info_doc},
  	{"byteswap",	(PyCFunction)array_byteswap, METH_VARARGS,
           byteswap_doc},
! /*	{"count",	(method)array_count},*/
  	{"fromfile",	(PyCFunction)array_fromfile, 0, fromfile_doc},
  	{"fromlist",	(PyCFunction)array_fromlist, 0, fromlist_doc},
  	{"fromstring",	(PyCFunction)array_fromstring, 0, fromstring_doc},
! /*	{"index",	(method)array_index},*/
  	{"insert",	(PyCFunction)array_insert, 0, insert_doc},
  	{"read",	(PyCFunction)array_fromfile, 0, fromfile_doc},
! /*	{"remove",	(method)array_remove},*/
  	{"reverse",	(PyCFunction)array_reverse, 0, reverse_doc},
! /*	{"sort",	(method)array_sort},*/
  	{"tofile",	(PyCFunction)array_tofile, 0, tofile_doc},
  	{"tolist",	(PyCFunction)array_tolist, 0, tolist_doc},
  	{"tostring",	(PyCFunction)array_tostring, 0, tostring_doc},
--- 1240,1257 ----
  	{"buffer_info", (PyCFunction)array_buffer_info, 0, buffer_info_doc},
  	{"byteswap",	(PyCFunction)array_byteswap, METH_VARARGS,
           byteswap_doc},
! /*	{"count",	(PyCFunction)array_count, 0, count_doc},*/
!  	{"extend",      (PyCFunction)array_extend, 1, extend_doc},
  	{"fromfile",	(PyCFunction)array_fromfile, 0, fromfile_doc},
  	{"fromlist",	(PyCFunction)array_fromlist, 0, fromlist_doc},
  	{"fromstring",	(PyCFunction)array_fromstring, 0, fromstring_doc},
! /*	{"index",	(PyCFunction)array_index, 0, index_doc},*/
  	{"insert",	(PyCFunction)array_insert, 0, insert_doc},
+  	{"pop",		(PyCFunction)array_pop, 1, pop_doc},
  	{"read",	(PyCFunction)array_fromfile, 0, fromfile_doc},
! /*	{"remove",	(PyCFunction)array_remove, 0, remove_doc},*/
  	{"reverse",	(PyCFunction)array_reverse, 0, reverse_doc},
! /*	{"sort",	(PyCFunction)array_sort, 0, sort_doc},*/
  	{"tofile",	(PyCFunction)array_tofile, 0, tofile_doc},
  	{"tolist",	(PyCFunction)array_tolist, 0, tolist_doc},
  	{"tostring",	(PyCFunction)array_tostring, 0, tostring_doc},
***************
*** 1432,1441 ****
--- 1527,1538 ----
  append() -- append a new item to the end of the array\n\
  buffer_info() -- return information giving the current memory info\n\
  byteswap() -- byteswap all the items of the array\n\
+ extend() -- extend array by appending array elements\n\
  fromfile() -- read items from a file object\n\
  fromlist() -- append items from the list\n\
  fromstring() -- append items from the string\n\
  insert() -- insert a new item into the array at a provided position\n\
+ pop() -- remove and return item (default last)\n\
  read() -- DEPRECATED, use fromfile()\n\
  reverse() -- reverse the order of the items in the array\n\
  tofile() -- write all items to a file object\n\

--------------A1BB794F76124C6DB9BD056D--