mirror of https://github.com/python/cpython
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:
parent
5b8b1555de
commit
3d392eb327
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
||||||
|
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue