Merged revisions 58947-59004 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r58952 | christian.heimes | 2007-11-12 10:58:08 -0800 (Mon, 12 Nov 2007) | 6 lines

  readline module cleanup
  fixed indention to tabs
  use Py_RETURN_NONE macro
  added more error checks to on_completion_display_matches_hook

  open question: Does PyList_SetItem(l, i, o) steal a reference to o in the case of an error?
........
  r58956 | guido.van.rossum | 2007-11-12 12:06:40 -0800 (Mon, 12 Nov 2007) | 2 lines

  Add the test from issue 1704621 (the issue itself is already fixed here).
........
  r58963 | amaury.forgeotdarc | 2007-11-13 13:54:28 -0800 (Tue, 13 Nov 2007) | 23 lines

  Merge from py3k branch:
  Correction for issue1265 (pdb bug with "with" statement).

  When an unfinished generator-iterator is garbage collected, PyEval_EvalFrameEx
  is called with a GeneratorExit exception set.  This leads to funny results
  if the sys.settrace function itself makes use of generators.
  A visible effect is that the settrace function is reset to None.
  Another is that the eventual "finally" block of the generator is not called.

  It is necessary to save/restore the exception around the call to the trace
  function.

  This happens a lot with py3k: isinstance() of an ABCMeta instance runs
      def __instancecheck__(cls, instance):
          """Override for isinstance(instance, cls)."""
          return any(cls.__subclasscheck__(c)
                     for c in {instance.__class__, type(instance)})
  which lets an opened generator expression each time it returns True.

  Backport candidate, even if the case is less frequent in 2.5.
........
  r58968 | georg.brandl | 2007-11-14 05:59:09 -0800 (Wed, 14 Nov 2007) | 2 lines

  Remove dead link from random docs.
........
  r58971 | raymond.hettinger | 2007-11-14 14:56:16 -0800 (Wed, 14 Nov 2007) | 1 line

  Make __fields__ read-only.  Suggested by Issac Morland
........
  r58972 | raymond.hettinger | 2007-11-14 15:02:30 -0800 (Wed, 14 Nov 2007) | 1 line

  Add test for __fields__ being read-only
........
  r58975 | raymond.hettinger | 2007-11-14 18:44:53 -0800 (Wed, 14 Nov 2007) | 6 lines

  Accept Issac Morland's suggestion for __replace__ to allow multiple replacements
  (suprisingly, this simplifies the signature, improves clarity, and is comparably fast).
  Update the docs to reflect a previous change to the function name.
  Add an example to the docs showing how to override the default __repr__ method.
........
  r58976 | raymond.hettinger | 2007-11-14 18:55:42 -0800 (Wed, 14 Nov 2007) | 1 line

  Small improvement to the implementation of __replace__().
........
  r58977 | raymond.hettinger | 2007-11-14 18:58:20 -0800 (Wed, 14 Nov 2007) | 1 line

  Fixup example in docs.
........
  r58978 | raymond.hettinger | 2007-11-14 19:16:09 -0800 (Wed, 14 Nov 2007) | 1 line

  Example of multiple replacements.
........
  r58998 | raymond.hettinger | 2007-11-15 14:39:34 -0800 (Thu, 15 Nov 2007) | 1 line

  Add example for use cases requiring default values.
........
  r59000 | bill.janssen | 2007-11-15 15:03:03 -0800 (Thu, 15 Nov 2007) | 1 line

  add the certificate for the Python SVN repository for testing SSL
........
  r59004 | guido.van.rossum | 2007-11-15 16:24:44 -0800 (Thu, 15 Nov 2007) | 8 lines

  A patch from issue 1378 by roudkerk:

  Currently on Windows set_error() make use of a large array which maps
  socket error numbers to error messages.

  This patch removes that array and just lets PyErr_SetExcFromWindowsErr()
  generate the message by using the Win32 function FormatMessage().
........
This commit is contained in:
Guido van Rossum 2007-11-16 00:35:22 +00:00
parent 5b8b1555de
commit 3d392eb327
7 changed files with 147 additions and 203 deletions

View File

@ -10,7 +10,7 @@
This module implements high-performance container datatypes. Currently, This module implements high-performance container datatypes. Currently,
there are two datatypes, :class:`deque` and :class:`defaultdict`, and there are two datatypes, :class:`deque` and :class:`defaultdict`, and
one datatype factory function, :func:`named_tuple`. Python already one datatype factory function, :func:`namedtuple`. Python already
includes built-in containers, :class:`dict`, :class:`list`, includes built-in containers, :class:`dict`, :class:`list`,
:class:`set`, and :class:`tuple`. In addition, the optional :mod:`bsddb` :class:`set`, and :class:`tuple`. In addition, the optional :mod:`bsddb`
module has a :meth:`bsddb.btopen` method that can be used to create in-memory module has a :meth:`bsddb.btopen` method that can be used to create in-memory
@ -383,14 +383,14 @@ Setting the :attr:`default_factory` to :class:`set` makes the
.. _named-tuple-factory: .. _named-tuple-factory:
:func:`named_tuple` Factory Function for Tuples with Named Fields :func:`namedtuple` Factory Function for Tuples with Named Fields
----------------------------------------------------------------- -----------------------------------------------------------------
Named tuples assign meaning to each position in a tuple and allow for more readable, Named tuples assign meaning to each position in a tuple and allow for more readable,
self-documenting code. They can be used wherever regular tuples are used, and self-documenting code. They can be used wherever regular tuples are used, and
they add the ability to access fields by name instead of position index. they add the ability to access fields by name instead of position index.
.. function:: named_tuple(typename, fieldnames, [verbose]) .. function:: namedtuple(typename, fieldnames, [verbose])
Returns a new tuple subclass named *typename*. The new subclass is used to Returns a new tuple subclass named *typename*. The new subclass is used to
create tuple-like objects that have fields accessable by attribute lookup as create tuple-like objects that have fields accessable by attribute lookup as
@ -415,7 +415,7 @@ they add the ability to access fields by name instead of position index.
Example:: Example::
>>> Point = named_tuple('Point', 'x y', verbose=True) >>> Point = namedtuple('Point', 'x y', verbose=True)
class Point(tuple): class Point(tuple):
'Point(x, y)' 'Point(x, y)'
__slots__ = () __slots__ = ()
@ -428,8 +428,8 @@ Example::
'Return a new dict mapping field names to their values' 'Return a new dict mapping field names to their values'
return dict(zip(('x', 'y'), self)) return dict(zip(('x', 'y'), self))
def __replace__(self, field, value): def __replace__(self, field, value):
'Return a new Point object replacing one field with a new value' 'Return a new Point object replacing specified fields with new values'
return Point(**dict(zip(('x', 'y'), self) + [(field, value)])) return Point(**dict(zip(('x', 'y'), self) + kwds.items()))
x = property(itemgetter(0)) x = property(itemgetter(0))
y = property(itemgetter(1)) y = property(itemgetter(1))
@ -447,7 +447,7 @@ Example::
Named tuples are especially useful for assigning field names to result tuples returned Named tuples are especially useful for assigning field names to result tuples returned
by the :mod:`csv` or :mod:`sqlite3` modules:: by the :mod:`csv` or :mod:`sqlite3` modules::
EmployeeRecord = named_tuple('EmployeeRecord', 'name, age, title, department, paygrade') EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
from itertools import starmap from itertools import starmap
import csv import csv
@ -486,18 +486,18 @@ two additonal methods and a read-only attribute.
>>> p.__asdict__() >>> p.__asdict__()
{'x': 11, 'y': 22} {'x': 11, 'y': 22}
.. method:: somenamedtuple.__replace__(field, value) .. method:: somenamedtuple.__replace__(kwargs)
Return a new instance of the named tuple replacing the named *field* with a new *value*: Return a new instance of the named tuple replacing specified fields with new values:
:: ::
>>> p = Point(x=11, y=22) >>> p = Point(x=11, y=22)
>>> p.__replace__('x', 33) >>> p.__replace__(x=33)
Point(x=33, y=22) Point(x=33, y=22)
>>> for recordnum, record in inventory: >>> for partnum, record in inventory.items():
... inventory[recordnum] = record.replace('total', record.price * record.quantity) ... inventory[partnum] = record.__replace__(price=newprices[partnum], updated=time.now())
.. attribute:: somenamedtuple.__fields__ .. attribute:: somenamedtuple.__fields__
@ -509,11 +509,31 @@ two additonal methods and a read-only attribute.
>>> p.__fields__ # view the field names >>> p.__fields__ # view the field names
('x', 'y') ('x', 'y')
>>> Color = named_tuple('Color', 'red green blue') >>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = named_tuple('Pixel', Point.__fields__ + Color.__fields__) >>> Pixel = namedtuple('Pixel', Point.__fields__ + Color.__fields__)
>>> Pixel(11, 22, 128, 255, 0) >>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)' Pixel(x=11, y=22, red=128, green=255, blue=0)'
Since a named tuple is a regular Python class, it is easy to add or change
functionality. For example, the display format can be changed by overriding
the :meth:`__repr__` method:
::
>>> Point = namedtuple('Point', 'x y')
>>> Point.__repr__ = lambda self: 'Point(%.3f, %.3f)' % self
>>> Point(x=10, y=20)
Point(10.000, 20.000)
Default values can be implemented by starting with a prototype instance
and customizing it with :meth:`__replace__`:
::
>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> model_account = Account('<owner name>', 0.0, 0)
>>> johns_account = model_account.__replace__(owner='John')
.. rubric:: Footnotes .. rubric:: Footnotes
.. [#] For information on the star-operator see .. [#] For information on the star-operator see

View File

@ -282,8 +282,3 @@ Examples of basic usage::
Wichmann, B. A. & Hill, I. D., "Algorithm AS 183: An efficient and portable Wichmann, B. A. & Hill, I. D., "Algorithm AS 183: An efficient and portable
pseudo-random number generator", Applied Statistics 31 (1982) 188-190. pseudo-random number generator", Applied Statistics 31 (1982) 188-190.
http://www.npl.co.uk/ssfm/download/abstracts.html#196
A modern variation of the Wichmann-Hill generator that greatly increases the
period, and passes now-standard statistical tests that the original generator
failed.

View File

@ -30,7 +30,7 @@ def namedtuple(typename, field_names, verbose=False):
11 11
>>> Point(**d) # convert from a dictionary >>> Point(**d) # convert from a dictionary
Point(x=11, y=22) Point(x=11, y=22)
>>> p.__replace__('x', 100) # __replace__() is like str.replace() but targets a named field >>> p.__replace__(x=100) # __replace__() is like str.replace() but targets named fields
Point(x=100, y=22) Point(x=100, y=22)
""" """
@ -60,7 +60,7 @@ def namedtuple(typename, field_names, verbose=False):
template = '''class %(typename)s(tuple): template = '''class %(typename)s(tuple):
'%(typename)s(%(argtxt)s)' '%(typename)s(%(argtxt)s)'
__slots__ = () __slots__ = ()
__fields__ = %(field_names)r __fields__ = property(lambda self: %(field_names)r)
def __new__(cls, %(argtxt)s): def __new__(cls, %(argtxt)s):
return tuple.__new__(cls, (%(argtxt)s)) return tuple.__new__(cls, (%(argtxt)s))
def __repr__(self): def __repr__(self):
@ -68,9 +68,9 @@ def namedtuple(typename, field_names, verbose=False):
def __asdict__(self, dict=dict, zip=zip): def __asdict__(self, dict=dict, zip=zip):
'Return a new dict mapping field names to their values' 'Return a new dict mapping field names to their values'
return dict(zip(%(field_names)r, self)) return dict(zip(%(field_names)r, self))
def __replace__(self, field, value, dict=dict, zip=zip): def __replace__(self, **kwds):
'Return a new %(typename)s object replacing one field with a new value' 'Return a new %(typename)s object replacing specified fields with new values'
return %(typename)s(**dict(list(zip(%(field_names)r, self)) + [(field, value)])) \n''' % locals() return %(typename)s(**dict(zip(%(field_names)r, self) + kwds.items())) \n''' % locals()
for i, name in enumerate(field_names): for i, name in enumerate(field_names):
template += ' %s = property(itemgetter(%d))\n' % (name, i) template += ' %s = property(itemgetter(%d))\n' % (name, i)
if verbose: if verbose:
@ -103,6 +103,10 @@ if __name__ == '__main__':
p = Point(x=10, y=20) p = Point(x=10, y=20)
assert p == loads(dumps(p)) assert p == loads(dumps(p))
# test and demonstrate ability to override methods
Point.__repr__ = lambda self: 'Point(%.3f, %.3f)' % self
print p
import doctest import doctest
TestResults = namedtuple('TestResults', 'failed attempted') TestResults = namedtuple('TestResults', 'failed attempted')
print(TestResults(*doctest.testmod())) print(TestResults(*doctest.testmod()))

View File

@ -304,6 +304,13 @@ class CommonTest(unittest.TestCase):
self.assertEqual(self.type2test(s)*(-4), self.type2test([])) self.assertEqual(self.type2test(s)*(-4), self.type2test([]))
self.assertEqual(id(s), id(s*1)) self.assertEqual(id(s), id(s*1))
def test_bigrepeat(self):
x = self.type2test([0])
x *= 2**16
self.assertRaises(MemoryError, x.__mul__, 2**16)
if hasattr(x, '__imul__'):
self.assertRaises(MemoryError, x.__imul__, 2**16)
def test_subscript(self): def test_subscript(self):
a = self.type2test([10, 11]) a = self.type2test([10, 11])
self.assertEqual(a.__getitem__(0), 10) self.assertEqual(a.__getitem__(0), 10)

View File

@ -48,9 +48,17 @@ class TestNamedTuple(unittest.TestCase):
self.assert_('__dict__' not in dir(p)) # verify instance has no dict self.assert_('__dict__' not in dir(p)) # verify instance has no dict
self.assert_('__weakref__' not in dir(p)) self.assert_('__weakref__' not in dir(p))
self.assertEqual(p.__fields__, ('x', 'y')) # test __fields__ attribute self.assertEqual(p.__fields__, ('x', 'y')) # test __fields__ attribute
self.assertEqual(p.__replace__('x', 1), (1, 22)) # test __replace__ method self.assertEqual(p.__replace__(x=1), (1, 22)) # test __replace__ method
self.assertEqual(p.__asdict__(), dict(x=11, y=22)) # test __dict__ method self.assertEqual(p.__asdict__(), dict(x=11, y=22)) # test __dict__ method
# Verify that __fields__ is read-only
try:
p.__fields__ = ('F1' ,'F2')
except AttributeError:
pass
else:
self.fail('The __fields__ attribute needs to be read-only')
# verify that field string can have commas # verify that field string can have commas
Point = namedtuple('Point', 'x, y') Point = namedtuple('Point', 'x, y')
p = Point(x=11, y=22) p = Point(x=11, y=22)

View File

@ -59,8 +59,7 @@ parse_and_bind(PyObject *self, PyObject *args)
strcpy(copy, s); strcpy(copy, s);
rl_parse_and_bind(copy); rl_parse_and_bind(copy);
free(copy); /* Free the copy */ free(copy); /* Free the copy */
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_parse_and_bind, PyDoc_STRVAR(doc_parse_and_bind,
@ -79,8 +78,7 @@ read_init_file(PyObject *self, PyObject *args)
errno = rl_read_init_file(s); errno = rl_read_init_file(s);
if (errno) if (errno)
return PyErr_SetFromErrno(PyExc_IOError); return PyErr_SetFromErrno(PyExc_IOError);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_read_init_file, PyDoc_STRVAR(doc_read_init_file,
@ -100,8 +98,7 @@ read_history_file(PyObject *self, PyObject *args)
errno = read_history(s); errno = read_history(s);
if (errno) if (errno)
return PyErr_SetFromErrno(PyExc_IOError); return PyErr_SetFromErrno(PyExc_IOError);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
static int _history_length = -1; /* do not truncate history by default */ static int _history_length = -1; /* do not truncate history by default */
@ -124,8 +121,7 @@ write_history_file(PyObject *self, PyObject *args)
history_truncate_file(s, _history_length); history_truncate_file(s, _history_length);
if (errno) if (errno)
return PyErr_SetFromErrno(PyExc_IOError); return PyErr_SetFromErrno(PyExc_IOError);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_write_history_file, PyDoc_STRVAR(doc_write_history_file,
@ -143,8 +139,7 @@ set_history_length(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "i:set_history_length", &length)) if (!PyArg_ParseTuple(args, "i:set_history_length", &length))
return NULL; return NULL;
_history_length = length; _history_length = length;
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(set_history_length_doc, PyDoc_STRVAR(set_history_length_doc,
@ -195,8 +190,7 @@ set_hook(const char *funcname, PyObject **hook_var, PyObject *args)
PyErr_SetString(PyExc_TypeError, buf); PyErr_SetString(PyExc_TypeError, buf);
return NULL; return NULL;
} }
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
@ -218,7 +212,7 @@ set_completion_display_matches_hook(PyObject *self, PyObject *args)
/* We cannot set this hook globally, since it replaces the /* We cannot set this hook globally, since it replaces the
default completion display. */ default completion display. */
rl_completion_display_matches_hook = rl_completion_display_matches_hook =
completion_display_matches_hook ? completion_display_matches_hook ?
(rl_compdisp_func_t *)on_completion_display_matches_hook : 0; (rl_compdisp_func_t *)on_completion_display_matches_hook : 0;
#endif #endif
return result; return result;
@ -325,8 +319,7 @@ set_completer_delims(PyObject *self, PyObject *args)
} }
free((void*)rl_completer_word_break_characters); free((void*)rl_completer_word_break_characters);
rl_completer_word_break_characters = strdup(break_chars); rl_completer_word_break_characters = strdup(break_chars);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_set_completer_delims, PyDoc_STRVAR(doc_set_completer_delims,
@ -336,32 +329,31 @@ set the readline word delimiters for tab-completion");
static PyObject * static PyObject *
py_remove_history(PyObject *self, PyObject *args) py_remove_history(PyObject *self, PyObject *args)
{ {
int entry_number; int entry_number;
HIST_ENTRY *entry; HIST_ENTRY *entry;
if (!PyArg_ParseTuple(args, "i:remove_history", &entry_number)) if (!PyArg_ParseTuple(args, "i:remove_history", &entry_number))
return NULL; return NULL;
if (entry_number < 0) { if (entry_number < 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"History index cannot be negative"); "History index cannot be negative");
return NULL; return NULL;
} }
entry = remove_history(entry_number); entry = remove_history(entry_number);
if (!entry) { if (!entry) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"No history item at position %d", "No history item at position %d",
entry_number); entry_number);
return NULL; return NULL;
} }
/* free memory allocated for the history entry */ /* free memory allocated for the history entry */
if (entry->line) if (entry->line)
free(entry->line); free(entry->line);
if (entry->data) if (entry->data)
free(entry->data); free(entry->data);
free(entry); free(entry);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_remove_history, PyDoc_STRVAR(doc_remove_history,
@ -371,34 +363,34 @@ remove history item given by its position");
static PyObject * static PyObject *
py_replace_history(PyObject *self, PyObject *args) py_replace_history(PyObject *self, PyObject *args)
{ {
int entry_number; int entry_number;
char *line; char *line;
HIST_ENTRY *old_entry; HIST_ENTRY *old_entry;
if (!PyArg_ParseTuple(args, "is:replace_history", &entry_number, &line)) { if (!PyArg_ParseTuple(args, "is:replace_history", &entry_number,
return NULL; &line)) {
} return NULL;
if (entry_number < 0) { }
PyErr_SetString(PyExc_ValueError, if (entry_number < 0) {
"History index cannot be negative"); PyErr_SetString(PyExc_ValueError,
return NULL; "History index cannot be negative");
} return NULL;
old_entry = replace_history_entry(entry_number, line, (void *)NULL); }
if (!old_entry) { old_entry = replace_history_entry(entry_number, line, (void *)NULL);
PyErr_Format(PyExc_ValueError, if (!old_entry) {
"No history item at position %d", PyErr_Format(PyExc_ValueError,
entry_number); "No history item at position %d",
return NULL; entry_number);
} return NULL;
/* free memory allocated for the old history entry */ }
if (old_entry->line) /* free memory allocated for the old history entry */
free(old_entry->line); if (old_entry->line)
if (old_entry->data) free(old_entry->line);
free(old_entry->data); if (old_entry->data)
free(old_entry); free(old_entry->data);
free(old_entry);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_replace_history, PyDoc_STRVAR(doc_replace_history,
@ -416,8 +408,7 @@ py_add_history(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
add_history(line); add_history(line);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_add_history, PyDoc_STRVAR(doc_add_history,
@ -458,8 +449,7 @@ static PyObject *
get_completer(PyObject *self, PyObject *noargs) get_completer(PyObject *self, PyObject *noargs)
{ {
if (completer == NULL) { if (completer == NULL) {
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
Py_INCREF(completer); Py_INCREF(completer);
return completer; return completer;
@ -483,8 +473,7 @@ get_history_item(PyObject *self, PyObject *args)
if ((hist_ent = history_get(idx))) if ((hist_ent = history_get(idx)))
return PyUnicode_FromString(hist_ent->line); return PyUnicode_FromString(hist_ent->line);
else { else {
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
} }
@ -530,8 +519,7 @@ static PyObject *
py_clear_history(PyObject *self, PyObject *noarg) py_clear_history(PyObject *self, PyObject *noarg)
{ {
clear_history(); clear_history();
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_clear_history, PyDoc_STRVAR(doc_clear_history,
@ -549,8 +537,7 @@ insert_text(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s:insert_text", &s)) if (!PyArg_ParseTuple(args, "s:insert_text", &s))
return NULL; return NULL;
rl_insert_text(s); rl_insert_text(s);
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_insert_text, PyDoc_STRVAR(doc_insert_text,
@ -564,8 +551,7 @@ static PyObject *
redisplay(PyObject *self, PyObject *noarg) redisplay(PyObject *self, PyObject *noarg)
{ {
rl_redisplay(); rl_redisplay();
Py_INCREF(Py_None); Py_RETURN_NONE;
return Py_None;
} }
PyDoc_STRVAR(doc_redisplay, PyDoc_STRVAR(doc_redisplay,
@ -591,9 +577,9 @@ static struct PyMethodDef readline_methods[] =
METH_VARARGS, doc_get_history_item}, METH_VARARGS, doc_get_history_item},
{"get_current_history_length", (PyCFunction)get_current_history_length, {"get_current_history_length", (PyCFunction)get_current_history_length,
METH_NOARGS, doc_get_current_history_length}, METH_NOARGS, doc_get_current_history_length},
{"set_history_length", set_history_length, {"set_history_length", set_history_length,
METH_VARARGS, set_history_length_doc}, METH_VARARGS, set_history_length_doc},
{"get_history_length", get_history_length, {"get_history_length", get_history_length,
METH_NOARGS, get_history_length_doc}, METH_NOARGS, get_history_length_doc},
{"set_completer", set_completer, METH_VARARGS, doc_set_completer}, {"set_completer", set_completer, METH_VARARGS, doc_set_completer},
{"get_completer", get_completer, METH_NOARGS, doc_get_completer}, {"get_completer", get_completer, METH_NOARGS, doc_get_completer},
@ -605,8 +591,8 @@ static struct PyMethodDef readline_methods[] =
{"set_completer_delims", set_completer_delims, {"set_completer_delims", set_completer_delims,
METH_VARARGS, doc_set_completer_delims}, METH_VARARGS, doc_set_completer_delims},
{"add_history", py_add_history, METH_VARARGS, doc_add_history}, {"add_history", py_add_history, METH_VARARGS, doc_add_history},
{"remove_history_item", py_remove_history, METH_VARARGS, doc_remove_history}, {"remove_history_item", py_remove_history, METH_VARARGS, doc_remove_history},
{"replace_history_item", py_replace_history, METH_VARARGS, doc_replace_history}, {"replace_history_item", py_replace_history, METH_VARARGS, doc_replace_history},
{"get_completer_delims", get_completer_delims, {"get_completer_delims", get_completer_delims,
METH_NOARGS, doc_get_completer_delims}, METH_NOARGS, doc_get_completer_delims},
@ -633,7 +619,7 @@ on_hook(PyObject *func)
int result = 0; int result = 0;
if (func != NULL) { if (func != NULL) {
PyObject *r; PyObject *r;
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate = PyGILState_Ensure();
#endif #endif
r = PyObject_CallFunction(func, NULL); r = PyObject_CallFunction(func, NULL);
@ -652,7 +638,7 @@ on_hook(PyObject *func)
PyErr_Clear(); PyErr_Clear();
Py_XDECREF(r); Py_XDECREF(r);
done: done:
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyGILState_Release(gilstate); PyGILState_Release(gilstate);
#endif #endif
return result; return result;
@ -682,37 +668,37 @@ on_completion_display_matches_hook(char **matches,
int num_matches, int max_length) int num_matches, int max_length)
{ {
int i; int i;
PyObject *m, *s; PyObject *m=NULL, *s=NULL, *r=NULL;
PyObject *r;
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate = PyGILState_Ensure();
#endif #endif
m = PyList_New(num_matches); m = PyList_New(num_matches);
if (m == NULL)
goto error;
for (i = 0; i < num_matches; i++) { for (i = 0; i < num_matches; i++) {
s = PyUnicode_FromString(matches[i+1]); s = PyUnicode_FromString(matches[i+1]);
if (s) { if (s == NULL)
PyList_SetItem(m, i, s); goto error;
} if (PyList_SetItem(m, i, s) == -1)
else {
goto error; goto error;
}
} }
r = PyObject_CallFunction(completion_display_matches_hook, r = PyObject_CallFunction(completion_display_matches_hook,
"sOi", matches[0], m, max_length); "sOi", matches[0], m, max_length);
Py_DECREF(m), m=NULL; Py_DECREF(m), m=NULL;
if (r == NULL || if (r == NULL ||
(r != Py_None && PyInt_AsLong(r) == -1 && PyErr_Occurred())) { (r != Py_None && PyInt_AsLong(r) == -1 && PyErr_Occurred())) {
goto error; goto error;
} }
Py_XDECREF(r), r=NULL;
Py_DECREF(r); if (0) {
goto done; error:
error: PyErr_Clear();
PyErr_Clear(); Py_XDECREF(m);
Py_XDECREF(r); Py_XDECREF(r);
done: }
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyGILState_Release(gilstate); PyGILState_Release(gilstate);
#endif #endif

View File

@ -450,87 +450,11 @@ set_error(void)
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
int err_no = WSAGetLastError(); int err_no = WSAGetLastError();
static struct { /* PyErr_SetExcFromWindowsErr() invokes FormatMessage() which
int no; recognizes the error codes used by both GetLastError() and
const char *msg; WSAGetLastError */
} *msgp, msgs[] = { if (err_no)
{WSAEINTR, "Interrupted system call"}, return PyErr_SetExcFromWindowsErr(socket_error, err_no);
{WSAEBADF, "Bad file descriptor"},
{WSAEACCES, "Permission denied"},
{WSAEFAULT, "Bad address"},
{WSAEINVAL, "Invalid argument"},
{WSAEMFILE, "Too many open files"},
{WSAEWOULDBLOCK,
"The socket operation could not complete "
"without blocking"},
{WSAEINPROGRESS, "Operation now in progress"},
{WSAEALREADY, "Operation already in progress"},
{WSAENOTSOCK, "Socket operation on non-socket"},
{WSAEDESTADDRREQ, "Destination address required"},
{WSAEMSGSIZE, "Message too long"},
{WSAEPROTOTYPE, "Protocol wrong type for socket"},
{WSAENOPROTOOPT, "Protocol not available"},
{WSAEPROTONOSUPPORT, "Protocol not supported"},
{WSAESOCKTNOSUPPORT, "Socket type not supported"},
{WSAEOPNOTSUPP, "Operation not supported"},
{WSAEPFNOSUPPORT, "Protocol family not supported"},
{WSAEAFNOSUPPORT, "Address family not supported"},
{WSAEADDRINUSE, "Address already in use"},
{WSAEADDRNOTAVAIL, "Can't assign requested address"},
{WSAENETDOWN, "Network is down"},
{WSAENETUNREACH, "Network is unreachable"},
{WSAENETRESET, "Network dropped connection on reset"},
{WSAECONNABORTED, "Software caused connection abort"},
{WSAECONNRESET, "Connection reset by peer"},
{WSAENOBUFS, "No buffer space available"},
{WSAEISCONN, "Socket is already connected"},
{WSAENOTCONN, "Socket is not connected"},
{WSAESHUTDOWN, "Can't send after socket shutdown"},
{WSAETOOMANYREFS, "Too many references: can't splice"},
{WSAETIMEDOUT, "Operation timed out"},
{WSAECONNREFUSED, "Connection refused"},
{WSAELOOP, "Too many levels of symbolic links"},
{WSAENAMETOOLONG, "File name too long"},
{WSAEHOSTDOWN, "Host is down"},
{WSAEHOSTUNREACH, "No route to host"},
{WSAENOTEMPTY, "Directory not empty"},
{WSAEPROCLIM, "Too many processes"},
{WSAEUSERS, "Too many users"},
{WSAEDQUOT, "Disc quota exceeded"},
{WSAESTALE, "Stale NFS file handle"},
{WSAEREMOTE, "Too many levels of remote in path"},
{WSASYSNOTREADY, "Network subsystem is unvailable"},
{WSAVERNOTSUPPORTED, "WinSock version is not supported"},
{WSANOTINITIALISED,
"Successful WSAStartup() not yet performed"},
{WSAEDISCON, "Graceful shutdown in progress"},
/* Resolver errors */
{WSAHOST_NOT_FOUND, "No such host is known"},
{WSATRY_AGAIN, "Host not found, or server failed"},
{WSANO_RECOVERY, "Unexpected server error encountered"},
{WSANO_DATA, "Valid name without requested data"},
{WSANO_ADDRESS, "No address, look for MX record"},
{0, NULL}
};
if (err_no) {
PyObject *v;
const char *msg = "winsock error";
for (msgp = msgs; msgp->msg; msgp++) {
if (err_no == msgp->no) {
msg = msgp->msg;
break;
}
}
v = Py_BuildValue("(is)", err_no, msg);
if (v != NULL) {
PyErr_SetObject(socket_error, v);
Py_DECREF(v);
}
return NULL;
}
else
#endif #endif
#if defined(PYOS_OS2) && !defined(PYCC_GCC) #if defined(PYOS_OS2) && !defined(PYCC_GCC)