merge heads

This commit is contained in:
Benjamin Peterson 2011-09-06 07:57:38 -04:00
commit 388c0e2325
18 changed files with 176 additions and 37 deletions

View File

@ -598,6 +598,17 @@ The module :mod:`curses` defines the following functions:
Only one *ch* can be pushed before :meth:`getch` is called. Only one *ch* can be pushed before :meth:`getch` is called.
.. function:: unget_wch(ch)
Push *ch* so the next :meth:`get_wch` will return it.
.. note::
Only one *ch* can be pushed before :meth:`get_wch` is called.
.. versionadded:: 3.3
.. function:: ungetmouse(id, x, y, z, bstate) .. function:: ungetmouse(id, x, y, z, bstate)
Push a :const:`KEY_MOUSE` event onto the input queue, associating the given Push a :const:`KEY_MOUSE` event onto the input queue, associating the given

View File

@ -571,9 +571,9 @@ For an example of the usage of queues for interprocess communication see
Return ``True`` if the queue is full, ``False`` otherwise. Because of Return ``True`` if the queue is full, ``False`` otherwise. Because of
multithreading/multiprocessing semantics, this is not reliable. multithreading/multiprocessing semantics, this is not reliable.
.. method:: put(item[, block[, timeout]]) .. method:: put(obj[, block[, timeout]])
Put item into the queue. If the optional argument *block* is ``True`` Put obj into the queue. If the optional argument *block* is ``True``
(the default) and *timeout* is ``None`` (the default), block if necessary until (the default) and *timeout* is ``None`` (the default), block if necessary until
a free slot is available. If *timeout* is a positive number, it blocks at a free slot is available. If *timeout* is a positive number, it blocks at
most *timeout* seconds and raises the :exc:`queue.Full` exception if no most *timeout* seconds and raises the :exc:`queue.Full` exception if no
@ -582,9 +582,9 @@ For an example of the usage of queues for interprocess communication see
available, else raise the :exc:`queue.Full` exception (*timeout* is available, else raise the :exc:`queue.Full` exception (*timeout* is
ignored in that case). ignored in that case).
.. method:: put_nowait(item) .. method:: put_nowait(obj)
Equivalent to ``put(item, False)``. Equivalent to ``put(obj, False)``.
.. method:: get([block[, timeout]]) .. method:: get([block[, timeout]])

View File

@ -72,7 +72,7 @@ Extending files
--------------- ---------------
A configuration file can be extended (i.e. included) by other files. For this, A configuration file can be extended (i.e. included) by other files. For this,
a ``DEFAULT`` section must contain an ``extends`` key which value points to one a ``DEFAULT`` section must contain an ``extends`` key whose value points to one
or more files which will be merged into the current files by adding new sections or more files which will be merged into the current files by adding new sections
and fields. If a file loaded by ``extends`` contains sections or keys that and fields. If a file loaded by ``extends`` contains sections or keys that
already exist in the original file, they will not override the previous values. already exist in the original file, they will not override the previous values.

View File

@ -608,7 +608,7 @@ PyAPI_FUNC(Py_ssize_t) PyUnicode_AsWideChar(
/* Convert the Unicode object to a wide character string. The output string /* Convert the Unicode object to a wide character string. The output string
always ends with a nul character. If size is not NULL, write the number of always ends with a nul character. If size is not NULL, write the number of
wide characters (including the nul character) into *size. wide characters (excluding the null character) into *size.
Returns a buffer allocated by PyMem_Alloc() (use PyMem_Free() to free it) Returns a buffer allocated by PyMem_Alloc() (use PyMem_Free() to free it)
on success. On error, returns NULL, *size is undefined and raises a on success. On error, returns NULL, *size is undefined and raises a

View File

@ -40,9 +40,8 @@ class install_egg_info(Command):
"Creating "+self.install_dir) "Creating "+self.install_dir)
log.info("Writing %s", target) log.info("Writing %s", target)
if not self.dry_run: if not self.dry_run:
f = open(target, 'w') with open(target, 'w', encoding='UTF-8') as f:
self.distribution.metadata.write_pkg_file(f) self.distribution.metadata.write_pkg_file(f)
f.close()
def get_outputs(self): def get_outputs(self):
return self.outputs return self.outputs

View File

@ -306,7 +306,10 @@ class sdist(Command):
try: try:
self.filelist.process_template_line(line) self.filelist.process_template_line(line)
except DistutilsTemplateError as msg: # the call above can raise a DistutilsTemplateError for
# malformed lines, or a ValueError from the lower-level
# convert_path function
except (DistutilsTemplateError, ValueError) as msg:
self.warn("%s, line %d: %s" % (template.filename, self.warn("%s, line %d: %s" % (template.filename,
template.current_line, template.current_line,
msg)) msg))

View File

@ -1010,11 +1010,9 @@ class DistributionMetadata:
def write_pkg_info(self, base_dir): def write_pkg_info(self, base_dir):
"""Write the PKG-INFO file into the release tree. """Write the PKG-INFO file into the release tree.
""" """
pkg_info = open(os.path.join(base_dir, 'PKG-INFO'), 'w') with open(os.path.join(base_dir, 'PKG-INFO'), 'w',
try: encoding='UTF-8') as pkg_info:
self.write_pkg_file(pkg_info) self.write_pkg_file(pkg_info)
finally:
pkg_info.close()
def write_pkg_file(self, file): def write_pkg_file(self, file):
"""Write the PKG-INFO format data to a file object. """Write the PKG-INFO format data to a file object.

View File

@ -15,6 +15,7 @@ from distutils.tests.test_config import PyPIRCCommandTestCase
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
from distutils.spawn import find_executable from distutils.spawn import find_executable
from distutils.log import WARN from distutils.log import WARN
from distutils.filelist import FileList
from distutils.archive_util import ARCHIVE_FORMATS from distutils.archive_util import ARCHIVE_FORMATS
SETUP_PY = """ SETUP_PY = """
@ -78,9 +79,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
dist.include_package_data = True dist.include_package_data = True
cmd = sdist(dist) cmd = sdist(dist)
cmd.dist_dir = 'dist' cmd.dist_dir = 'dist'
def _warn(*args):
pass
cmd.warn = _warn
return dist, cmd return dist, cmd
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run') @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
@ -235,7 +233,8 @@ class SDistTestCase(PyPIRCCommandTestCase):
# with the `check` subcommand # with the `check` subcommand
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
warnings = self.get_logs(WARN) warnings = [msg for msg in self.get_logs(WARN) if
msg.startswith('warning: check:')]
self.assertEqual(len(warnings), 2) self.assertEqual(len(warnings), 2)
# trying with a complete set of metadata # trying with a complete set of metadata
@ -244,7 +243,8 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.metadata_check = 0 cmd.metadata_check = 0
cmd.run() cmd.run()
warnings = self.get_logs(WARN) warnings = [msg for msg in self.get_logs(WARN) if
msg.startswith('warning: check:')]
self.assertEqual(len(warnings), 0) self.assertEqual(len(warnings), 0)
def test_check_metadata_deprecated(self): def test_check_metadata_deprecated(self):
@ -266,7 +266,6 @@ class SDistTestCase(PyPIRCCommandTestCase):
self.assertEqual(len(output), num_formats) self.assertEqual(len(output), num_formats)
def test_finalize_options(self): def test_finalize_options(self):
dist, cmd = self.get_cmd() dist, cmd = self.get_cmd()
cmd.finalize_options() cmd.finalize_options()
@ -286,6 +285,32 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.formats = 'supazipa' cmd.formats = 'supazipa'
self.assertRaises(DistutilsOptionError, cmd.finalize_options) self.assertRaises(DistutilsOptionError, cmd.finalize_options)
# the following tests make sure there is a nice error message instead
# of a traceback when parsing an invalid manifest template
def _test_template(self, content):
dist, cmd = self.get_cmd()
os.chdir(self.tmp_dir)
self.write_file('MANIFEST.in', content)
cmd.ensure_finalized()
cmd.filelist = FileList()
cmd.read_template()
warnings = self.get_logs(WARN)
self.assertEqual(len(warnings), 1)
def test_invalid_template_unknown_command(self):
self._test_template('taunt knights *')
def test_invalid_template_wrong_arguments(self):
# this manifest command takes one argument
self._test_template('prune')
@unittest.skipIf(os.name != 'nt', 'test relevant for Windows only')
def test_invalid_template_wrong_path(self):
# on Windows, trailing slashes are not allowed
# this used to crash instead of raising a warning: #8286
self._test_template('include examples/')
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run') @unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_get_file_list(self): def test_get_file_list(self):
# make sure MANIFEST is recalculated # make sure MANIFEST is recalculated

View File

@ -458,4 +458,4 @@ class HTMLParser(_markupbase.ParserBase):
return '&'+s+';' return '&'+s+';'
return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));",
replaceEntities, s, re.ASCII) replaceEntities, s, flags=re.ASCII)

View File

@ -946,7 +946,7 @@ class PackagingLibChecks(support.TempdirManager,
def _distutils_pkg_info(self): def _distutils_pkg_info(self):
tmp = self._distutils_setup_py_pkg() tmp = self._distutils_setup_py_pkg()
self.write_file([tmp, 'PKG-INFO'], '') self.write_file([tmp, 'PKG-INFO'], '', encoding='UTF-8')
return tmp return tmp
def _setup_cfg_with_no_metadata_pkg(self): def _setup_cfg_with_no_metadata_pkg(self):
@ -971,7 +971,7 @@ class PackagingLibChecks(support.TempdirManager,
def _pkg_info_with_no_distutils(self): def _pkg_info_with_no_distutils(self):
tmp = self._random_setup_py_pkg() tmp = self._random_setup_py_pkg()
self.write_file([tmp, 'PKG-INFO'], '') self.write_file([tmp, 'PKG-INFO'], '', encoding='UTF-8')
return tmp return tmp
def _random_setup_py_pkg(self): def _random_setup_py_pkg(self):

View File

@ -2366,17 +2366,11 @@ class TarFile(object):
try: try:
g = grp.getgrnam(tarinfo.gname)[2] g = grp.getgrnam(tarinfo.gname)[2]
except KeyError: except KeyError:
try: g = tarinfo.gid
g = grp.getgrgid(tarinfo.gid)[2]
except KeyError:
g = os.getgid()
try: try:
u = pwd.getpwnam(tarinfo.uname)[2] u = pwd.getpwnam(tarinfo.uname)[2]
except KeyError: except KeyError:
try: u = tarinfo.uid
u = pwd.getpwuid(tarinfo.uid)[2]
except KeyError:
u = os.getuid()
try: try:
if tarinfo.issym() and hasattr(os, "lchown"): if tarinfo.issym() and hasattr(os, "lchown"):
os.lchown(targetpath, u, g) os.lchown(targetpath, u, g)

View File

@ -264,6 +264,22 @@ def test_issue6243(stdscr):
curses.ungetch(1025) curses.ungetch(1025)
stdscr.getkey() stdscr.getkey()
def test_unget_wch(stdscr):
if not hasattr(curses, 'unget_wch'):
return
ch = 'a'
curses.unget_wch(ch)
read = stdscr.get_wch()
read = chr(read)
if read != ch:
raise AssertionError("%r != %r" % (read, ch))
ch = ord('a')
curses.unget_wch(ch)
read = stdscr.get_wch()
if read != ch:
raise AssertionError("%r != %r" % (read, ch))
def main(stdscr): def main(stdscr):
curses.savetty() curses.savetty()
try: try:
@ -272,6 +288,7 @@ def main(stdscr):
test_userptr_without_set(stdscr) test_userptr_without_set(stdscr)
test_resize_term(stdscr) test_resize_term(stdscr)
test_issue6243(stdscr) test_issue6243(stdscr)
test_unget_wch(stdscr)
finally: finally:
curses.resetty() curses.resetty()

View File

@ -377,7 +377,8 @@ class HTMLParserTolerantTestCase(TestCaseBase):
p = html.parser.HTMLParser() p = html.parser.HTMLParser()
self.assertEqual(p.unescape('&#bad;'),'&#bad;') self.assertEqual(p.unescape('&#bad;'),'&#bad;')
self.assertEqual(p.unescape('&'),'&') self.assertEqual(p.unescape('&'),'&')
# see #12888
self.assertEqual(p.unescape('{ ' * 1050), '{ ' * 1050)
def test_main(): def test_main():
support.run_unittest(HTMLParserTestCase, HTMLParserTolerantTestCase) support.run_unittest(HTMLParserTestCase, HTMLParserTolerantTestCase)

View File

@ -704,6 +704,7 @@ Douglas Orr
Michele Orrù Michele Orrù
Oleg Oshmyan Oleg Oshmyan
Denis S. Otkidach Denis S. Otkidach
Peter Otten
Michael Otteneder Michael Otteneder
R. M. Oudkerk R. M. Oudkerk
Russel Owen Russel Owen

View File

@ -271,6 +271,23 @@ Core and Builtins
Library Library
------- -------
- Issue #12567: Add curses.unget_wch() function. Push a character so the next
get_wch() will return it.
- Issue #9561: distutils and packaging now writes egg-info files using UTF-8,
instead of the locale encoding.
- Issue #8286: The distutils command sdist will print a warning message instead
of crashing when an invalid path is given in the manifest template.
- Issue #12841: tarfile unnecessarily checked the existence of numerical user
and group ids on extraction. If one of them did not exist the respective id
of the current user (i.e. root) was used for the file and ownership
information was lost.
- Issue #12888: Fix a bug in HTMLParser.unescape that prevented it to escape
more than 128 entities. Patch by Peter Otten.
- Issue #12878: Expose a __dict__ attribute on io.IOBase and its subclasses. - Issue #12878: Expose a __dict__ attribute on io.IOBase and its subclasses.
- Issue #12636: IDLE reads the coding cookie when executing a Python script. - Issue #12636: IDLE reads the coding cookie when executing a Python script.

View File

@ -2696,6 +2696,71 @@ PyCurses_UngetCh(PyObject *self, PyObject *args)
return PyCursesCheckERR(ungetch(ch), "ungetch"); return PyCursesCheckERR(ungetch(ch), "ungetch");
} }
#ifdef HAVE_NCURSESW
/* Convert an object to a character (wchar_t):
- int
- str of length 1
Return 1 on success, 0 on error. */
static int
PyCurses_ConvertToWchar_t(PyObject *obj,
wchar_t *wch)
{
if (PyUnicode_Check(obj)) {
wchar_t buffer[2];
if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
PyErr_Format(PyExc_TypeError,
"expect bytes or str of length 1, or int, "
"got a str of length %zi",
PyUnicode_GET_SIZE(obj));
return 0;
}
*wch = buffer[0];
return 2;
}
else if (PyLong_CheckExact(obj)) {
long value;
int overflow;
value = PyLong_AsLongAndOverflow(obj, &overflow);
if (overflow) {
PyErr_SetString(PyExc_OverflowError,
"int doesn't fit in long");
return 0;
}
*wch = (wchar_t)value;
if ((long)*wch != value) {
PyErr_Format(PyExc_OverflowError,
"character doesn't fit in wchar_t");
return 0;
}
return 1;
}
else {
PyErr_Format(PyExc_TypeError,
"expect bytes or str of length 1, or int, got %s",
Py_TYPE(obj)->tp_name);
return 0;
}
}
static PyObject *
PyCurses_Unget_Wch(PyObject *self, PyObject *args)
{
PyObject *obj;
wchar_t wch;
PyCursesInitialised;
if (!PyArg_ParseTuple(args,"O", &obj))
return NULL;
if (!PyCurses_ConvertToWchar_t(obj, &wch))
return NULL;
return PyCursesCheckERR(unget_wch(wch), "unget_wch");
}
#endif
static PyObject * static PyObject *
PyCurses_Use_Env(PyObject *self, PyObject *args) PyCurses_Use_Env(PyObject *self, PyObject *args)
{ {
@ -2823,6 +2888,9 @@ static PyMethodDef PyCurses_methods[] = {
{"typeahead", (PyCFunction)PyCurses_TypeAhead, METH_VARARGS}, {"typeahead", (PyCFunction)PyCurses_TypeAhead, METH_VARARGS},
{"unctrl", (PyCFunction)PyCurses_UnCtrl, METH_VARARGS}, {"unctrl", (PyCFunction)PyCurses_UnCtrl, METH_VARARGS},
{"ungetch", (PyCFunction)PyCurses_UngetCh, METH_VARARGS}, {"ungetch", (PyCFunction)PyCurses_UngetCh, METH_VARARGS},
#ifdef HAVE_NCURSESW
{"unget_wch", (PyCFunction)PyCurses_Unget_Wch, METH_VARARGS},
#endif
{"use_env", (PyCFunction)PyCurses_Use_Env, METH_VARARGS}, {"use_env", (PyCFunction)PyCurses_Use_Env, METH_VARARGS},
#ifndef STRICT_SYSV_CURSES #ifndef STRICT_SYSV_CURSES
{"use_default_colors", (PyCFunction)PyCurses_Use_Default_Colors, METH_NOARGS}, {"use_default_colors", (PyCFunction)PyCurses_Use_Default_Colors, METH_NOARGS},

View File

@ -1204,12 +1204,12 @@ PyUnicode_FromFormat(const char *format, ...)
/* Helper function for PyUnicode_AsWideChar() and PyUnicode_AsWideCharString(): /* Helper function for PyUnicode_AsWideChar() and PyUnicode_AsWideCharString():
convert a Unicode object to a wide character string. convert a Unicode object to a wide character string.
- If w is NULL: return the number of wide characters (including the nul - If w is NULL: return the number of wide characters (including the null
character) required to convert the unicode object. Ignore size argument. character) required to convert the unicode object. Ignore size argument.
- Otherwise: return the number of wide characters (excluding the nul - Otherwise: return the number of wide characters (excluding the null
character) written into w. Write at most size wide characters (including character) written into w. Write at most size wide characters (including
the nul character). */ the null character). */
static Py_ssize_t static Py_ssize_t
unicode_aswidechar(PyUnicodeObject *unicode, unicode_aswidechar(PyUnicodeObject *unicode,
wchar_t *w, wchar_t *w,
@ -1257,7 +1257,7 @@ unicode_aswidechar(PyUnicodeObject *unicode,
return w - worig; return w - worig;
} }
else { else {
nchar = 1; /* nul character at the end */ nchar = 1; /* null character at the end */
while (u != uend) { while (u != uend) {
if (0xD800 <= u[0] && u[0] <= 0xDBFF if (0xD800 <= u[0] && u[0] <= 0xDBFF
&& 0xDC00 <= u[1] && u[1] <= 0xDFFF) && 0xDC00 <= u[1] && u[1] <= 0xDFFF)
@ -1295,7 +1295,7 @@ unicode_aswidechar(PyUnicodeObject *unicode,
return w - worig; return w - worig;
} }
else { else {
nchar = 1; /* nul character */ nchar = 1; /* null character */
while (u != uend) { while (u != uend) {
if (*u > 0xffff) if (*u > 0xffff)
nchar += 2; nchar += 2;

View File

@ -30,4 +30,9 @@ product_codes = {
'3.2.1121':'{4f90de4a-83dd-4443-b625-ca130ff361dd}', # 3.2.1rc1 '3.2.1121':'{4f90de4a-83dd-4443-b625-ca130ff361dd}', # 3.2.1rc1
'3.2.1122':'{dc5eb04d-ff8a-4bed-8f96-23942fd59e5f}', # 3.2.1rc2 '3.2.1122':'{dc5eb04d-ff8a-4bed-8f96-23942fd59e5f}', # 3.2.1rc2
'3.2.1150':'{34b2530c-6349-4292-9dc3-60bda4aed93c}', # 3.2.1 '3.2.1150':'{34b2530c-6349-4292-9dc3-60bda4aed93c}', # 3.2.1
'3.2.2121':'{DFB29A53-ACC4-44e6-85A6-D0DA26FE8E4E}', # 3.2.2rc1
'3.2.2150':'{4CDE3168-D060-4b7c-BC74-4D8F9BB01AFD}', # 3.2.2
'3.2.3121':'{B8E8CFF7-E4C6-4a7c-9F06-BB3A8B75DDA8}', # 3.2.3rc1
'3.2.3150':'{789C9644-9F82-44d3-B4CA-AC31F46F5882}', # 3.2.3
} }