summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/datetime.rst65
-rw-r--r--Doc/library/email.generator.rst17
-rw-r--r--Doc/library/json.rst4
-rw-r--r--Doc/library/threading.rst13
-rw-r--r--Lib/_strptime.py8
-rw-r--r--Lib/test/test_bisect.py47
-rw-r--r--Lib/test/test_pkgutil.py51
-rw-r--r--Lib/test/test_strptime.py5
-rw-r--r--Lib/test/test_urllib2.py16
-rw-r--r--Lib/tkinter/__init__.py28
-rw-r--r--Lib/urllib/request.py6
-rw-r--r--Misc/NEWS12
-rw-r--r--Modules/_bisectmodule.c3
-rw-r--r--Objects/rangeobject.c2
-rw-r--r--Tools/buildbot/external-common.bat3
15 files changed, 228 insertions, 52 deletions
diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst
index 1c4e9b9..f7e8762 100644
--- a/Doc/library/datetime.rst
+++ b/Doc/library/datetime.rst
@@ -12,28 +12,34 @@
The :mod:`datetime` module supplies classes for manipulating dates and times in
both simple and complex ways. While date and time arithmetic is supported, the
focus of the implementation is on efficient attribute extraction for output
-formatting and manipulation. For related
-functionality, see also the :mod:`time` and :mod:`calendar` modules.
-
-There are two kinds of date and time objects: "naive" and "aware". This
-distinction refers to whether the object has any notion of time zone, daylight
-saving time, or other kind of algorithmic or political time adjustment. Whether
-a naive :class:`.datetime` object represents Coordinated Universal Time (UTC),
-local time, or time in some other timezone is purely up to the program, just
-like it's up to the program whether a particular number represents metres,
-miles, or mass. Naive :class:`.datetime` objects are easy to understand and to
-work with, at the cost of ignoring some aspects of reality.
-
-For applications requiring more, :class:`.datetime` and :class:`.time` objects
-have an optional time zone information attribute, :attr:`tzinfo`, that can be
-set to an instance of a subclass of the abstract :class:`tzinfo` class. These
-:class:`tzinfo` objects capture information about the offset from UTC time, the
-time zone name, and whether Daylight Saving Time is in effect. Note that only
-one concrete :class:`tzinfo` class, the :class:`timezone` class, is supplied by the
-:mod:`datetime` module. The :class:`timezone` class can represent simple
-timezones with fixed offset from UTC such as UTC itself or North American EST and
-EDT timezones. Supporting timezones at whatever level of detail is
-required is up to the application. The rules for time adjustment across the
+formatting and manipulation. For related functionality, see also the
+:mod:`time` and :mod:`calendar` modules.
+
+There are two kinds of date and time objects: "naive" and "aware".
+
+An aware object has sufficient knowledge of applicable algorithmic and
+political time adjustments, such as time zone and daylight saving time
+information, to locate itself relative to other aware objects. An aware object
+is used to represent a specific moment in time that is not open to
+interpretation [#]_.
+
+A naive object does not contain enough information to unambiguously locate
+itself relative to other date/time objects. Whether a naive object represents
+Coordinated Universal Time (UTC), local time, or time in some other timezone is
+purely up to the program, just like it is up to the program whether a
+particular number represents metres, miles, or mass. Naive objects are easy to
+understand and to work with, at the cost of ignoring some aspects of reality.
+
+For applications requiring aware objects, :class:`.datetime` and :class:`.time`
+objects have an optional time zone information attribute, :attr:`tzinfo`, that
+can be set to an instance of a subclass of the abstract :class:`tzinfo` class.
+These :class:`tzinfo` objects capture information about the offset from UTC
+time, the time zone name, and whether Daylight Saving Time is in effect. Note
+that only one concrete :class:`tzinfo` class, the :class:`timezone` class, is
+supplied by the :mod:`datetime` module. The :class:`timezone` class can
+represent simple timezones with fixed offset from UTC, such as UTC itself or
+North American EST and EDT timezones. Supporting timezones at deeper levels of
+detail is up to the application. The rules for time adjustment across the
world are more political than rational, change frequently, and there is no
standard suitable for every application aside from UTC.
@@ -114,10 +120,13 @@ Objects of these types are immutable.
Objects of the :class:`date` type are always naive.
-An object *d* of type :class:`.time` or :class:`.datetime` may be naive or aware.
-*d* is aware if ``d.tzinfo`` is not ``None`` and ``d.tzinfo.utcoffset(d)`` does
-not return ``None``. If ``d.tzinfo`` is ``None``, or if ``d.tzinfo`` is not
-``None`` but ``d.tzinfo.utcoffset(d)`` returns ``None``, *d* is naive.
+An object of type :class:`.time` or :class:`.datetime` may be naive or aware.
+A :class:`.datetime` object *d* is aware if ``d.tzinfo`` is not ``None`` and
+``d.tzinfo.utcoffset(d)`` does not return ``None``. If ``d.tzinfo`` is
+``None``, or if ``d.tzinfo`` is not ``None`` but ``d.tzinfo.utcoffset(d)``
+returns ``None``, *d* is naive. A :class:`.time` object *t* is aware
+if ``t.tzinfo`` is not ``None`` and ``t.tzinfo.utcoffset(None)`` does not return
+``None``. Otherwise, *t* is naive.
The distinction between naive and aware doesn't apply to :class:`timedelta`
objects.
@@ -1806,3 +1815,7 @@ Notes:
When the ``%z`` directive is provided to the :meth:`strptime` method, an
aware :class:`.datetime` object will be produced. The ``tzinfo`` of the
result will be set to a :class:`timezone` instance.
+
+.. rubric:: Footnotes
+
+.. [#] If, that is, we ignore the effects of Relativity
diff --git a/Doc/library/email.generator.rst b/Doc/library/email.generator.rst
index 85b32fe..f40869c 100644
--- a/Doc/library/email.generator.rst
+++ b/Doc/library/email.generator.rst
@@ -17,10 +17,10 @@ yourself. However the bundled generator knows how to generate most email in a
standards-compliant way, should handle MIME and non-MIME email messages just
fine, and is designed so that the transformation from flat text, to a message
structure via the :class:`~email.parser.Parser` class, and back to flat text,
-is idempotent (the input is identical to the output). On the other hand, using
-the Generator on a :class:`~email.message.Message` constructed by program may
-result in changes to the :class:`~email.message.Message` object as defaults are
-filled in.
+is idempotent (the input is identical to the output) [#]_. On the other hand,
+using the Generator on a :class:`~email.message.Message` constructed by program
+may result in changes to the :class:`~email.message.Message` object as defaults
+are filled in.
:class:`bytes` output can be generated using the :class:`BytesGenerator` class.
If the message object structure contains non-ASCII bytes, this generator's
@@ -204,3 +204,12 @@ representing the part.
The default value for *fmt* is ``None``, meaning ::
[Non-text (%(type)s) part of message omitted, filename %(filename)s]
+
+
+.. rubric:: Footnotes
+
+.. [#] This statement assumes that you use the appropriate setting for the
+ ``unixfrom`` argument, and that you set maxheaderlen=0 (which will
+ preserve whatever the input line lengths were). It is also not strictly
+ true, since in many cases runs of whitespace in headers are collapsed
+ into single blanks. The latter is a bug that will eventually be fixed.
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
index c2ad6e9..cbcac8d 100644
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -209,8 +209,8 @@ Basic Usage
(e.g. :class:`float`).
*parse_constant*, if specified, will be called with one of the following
- strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``, ``'null'``, ``'true'``,
- ``'false'``. This can be used to raise an exception if invalid JSON numbers
+ strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``.
+ This can be used to raise an exception if invalid JSON numbers
are encountered.
To use a custom :class:`JSONDecoder` subclass, specify it with the ``cls``
diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
index 30f7ece..43087ef 100644
--- a/Doc/library/threading.rst
+++ b/Doc/library/threading.rst
@@ -403,15 +403,12 @@ All methods are executed atomically.
Acquire a lock, blocking or non-blocking.
- When invoked without arguments, block until the lock is unlocked, then set it to
- locked, and return true.
+ When invoked with the *blocking* argument set to ``True`` (the default),
+ block until the lock is unlocked, then set it to locked and return ``True``.
- When invoked with the *blocking* argument set to true, do the same thing as when
- called without arguments, and return true.
-
- When invoked with the *blocking* argument set to false, do not block. If a call
- without an argument would block, return false immediately; otherwise, do the
- same thing as when called without arguments, and return true.
+ When invoked with the *blocking* argument set to ``False``, do not block.
+ If a call with *blocking* set to ``True`` would block, return ``False``
+ immediately; otherwise, set the lock to locked and return ``True``.
When invoked with the floating-point *timeout* argument set to a positive
value, block for at most the number of seconds specified by *timeout*
diff --git a/Lib/_strptime.py b/Lib/_strptime.py
index 0106e91..fa06376 100644
--- a/Lib/_strptime.py
+++ b/Lib/_strptime.py
@@ -444,8 +444,10 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
else:
tz = value
break
+ leap_year_fix = False
if year is None and month == 2 and day == 29:
year = 1904 # 1904 is first leap year of 20th century
+ leap_year_fix = True
elif year is None:
year = 1900
# If we know the week of the year and what day of that week, we can figure
@@ -476,6 +478,12 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
else:
gmtoff = None
+ if leap_year_fix:
+ # the caller didn't supply a year but asked for Feb 29th. We couldn't
+ # use the default of 1900 for computations. We set it back to ensure
+ # that February 29th is smaller than March 1st.
+ year = 1900
+
return (year, month, day,
hour, minute, second,
weekday, julian, tz, gmtoff, tzname), fraction
diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py
index c24a1a2..2ac3a68 100644
--- a/Lib/test/test_bisect.py
+++ b/Lib/test/test_bisect.py
@@ -23,6 +23,28 @@ del sys.modules['bisect']
import bisect as c_bisect
+class Range(object):
+ """A trivial range()-like object without any integer width limitations."""
+ def __init__(self, start, stop):
+ self.start = start
+ self.stop = stop
+ self.last_insert = None
+
+ def __len__(self):
+ return self.stop - self.start
+
+ def __getitem__(self, idx):
+ n = self.stop - self.start
+ if idx < 0:
+ idx += n
+ if idx >= n:
+ raise IndexError(idx)
+ return self.start + idx
+
+ def insert(self, idx, item):
+ self.last_insert = idx, item
+
+
class TestBisect(unittest.TestCase):
module = None
@@ -125,9 +147,28 @@ class TestBisect(unittest.TestCase):
def test_large_range(self):
# Issue 13496
mod = self.module
- data = range(sys.maxsize-1)
- self.assertEqual(mod.bisect_left(data, sys.maxsize-3), sys.maxsize-3)
- self.assertEqual(mod.bisect_right(data, sys.maxsize-3), sys.maxsize-2)
+ n = sys.maxsize
+ data = range(n-1)
+ self.assertEqual(mod.bisect_left(data, n-3), n-3)
+ self.assertEqual(mod.bisect_right(data, n-3), n-2)
+ self.assertEqual(mod.bisect_left(data, n-3, n-10, n), n-3)
+ self.assertEqual(mod.bisect_right(data, n-3, n-10, n), n-2)
+
+ def test_large_pyrange(self):
+ # Same as above, but without C-imposed limits on range() parameters
+ mod = self.module
+ n = sys.maxsize
+ data = Range(0, n-1)
+ self.assertEqual(mod.bisect_left(data, n-3), n-3)
+ self.assertEqual(mod.bisect_right(data, n-3), n-2)
+ self.assertEqual(mod.bisect_left(data, n-3, n-10, n), n-3)
+ self.assertEqual(mod.bisect_right(data, n-3, n-10, n), n-2)
+ x = n - 100
+ mod.insort_left(data, x, x - 50, x + 50)
+ self.assertEqual(data.last_insert, (x, x))
+ x = n - 200
+ mod.insort_right(data, x, x - 50, x + 50)
+ self.assertEqual(data.last_insert, (x + 1, x))
def test_random(self, n=25):
from random import randrange
diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py
index f4e0323..6025bcd 100644
--- a/Lib/test/test_pkgutil.py
+++ b/Lib/test/test_pkgutil.py
@@ -137,8 +137,57 @@ class PkgutilPEP302Tests(unittest.TestCase):
self.assertEqual(foo.loads, 1)
del sys.modules['foo']
+
+class ExtendPathTests(unittest.TestCase):
+ def create_init(self, pkgname):
+ dirname = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, dirname)
+ sys.path.insert(0, dirname)
+
+ pkgdir = os.path.join(dirname, pkgname)
+ os.mkdir(pkgdir)
+ with open(os.path.join(pkgdir, '__init__.py'), 'w') as fl:
+ fl.write('from pkgutil import extend_path\n__path__ = extend_path(__path__, __name__)\n')
+
+ return dirname
+
+ def create_submodule(self, dirname, pkgname, submodule_name, value):
+ module_name = os.path.join(dirname, pkgname, submodule_name + '.py')
+ with open(module_name, 'w') as fl:
+ print('value={}'.format(value), file=fl)
+
+ def setUp(self):
+ # Create 2 directories on sys.path
+ self.pkgname = 'foo'
+ self.dirname_0 = self.create_init(self.pkgname)
+ self.dirname_1 = self.create_init(self.pkgname)
+
+ def tearDown(self):
+ del sys.path[0]
+ del sys.path[0]
+ del sys.modules['foo']
+ del sys.modules['foo.bar']
+ del sys.modules['foo.baz']
+
+ def test_simple(self):
+ self.create_submodule(self.dirname_0, self.pkgname, 'bar', 0)
+ self.create_submodule(self.dirname_1, self.pkgname, 'baz', 1)
+ import foo.bar
+ import foo.baz
+ # Ensure we read the expected values
+ self.assertEqual(foo.bar.value, 0)
+ self.assertEqual(foo.baz.value, 1)
+
+ # Ensure the path is set up correctly
+ self.assertEqual(sorted(foo.__path__),
+ sorted([os.path.join(self.dirname_0, self.pkgname),
+ os.path.join(self.dirname_1, self.pkgname)]))
+
+ # XXX: test .pkg files
+
+
def test_main():
- run_unittest(PkgutilTests, PkgutilPEP302Tests)
+ run_unittest(PkgutilTests, PkgutilPEP302Tests, ExtendPathTests)
# this is necessary if test is run repeated (like when finding leaks)
import zipimport
zipimport._zip_directory_cache.clear()
diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py
index 7245671..90aac5b 100644
--- a/Lib/test/test_strptime.py
+++ b/Lib/test/test_strptime.py
@@ -381,6 +381,11 @@ class StrptimeTests(unittest.TestCase):
def test_feb29_on_leap_year_without_year(self):
time.strptime("Feb 29", "%b %d")
+ def test_mar1_comes_after_feb29_even_when_omitting_the_year(self):
+ self.assertLess(
+ time.strptime("Feb 29", "%b %d"),
+ time.strptime("Mar 1", "%b %d"))
+
class Strptime12AMPMTests(unittest.TestCase):
"""Test a _strptime regression in '%I %p' at 12 noon (12 PM)"""
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 3d80e01..3ace66e 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -1218,6 +1218,22 @@ class HandlerTests(unittest.TestCase):
def test_basic_auth_with_single_quoted_realm(self):
self.test_basic_auth(quote_char="'")
+ def test_basic_auth_with_unquoted_realm(self):
+ opener = OpenerDirector()
+ password_manager = MockPasswordManager()
+ auth_handler = urllib.request.HTTPBasicAuthHandler(password_manager)
+ realm = "ACME Widget Store"
+ http_handler = MockHTTPHandler(
+ 401, 'WWW-Authenticate: Basic realm=%s\r\n\r\n' % realm)
+ opener.add_handler(auth_handler)
+ opener.add_handler(http_handler)
+ with self.assertWarns(UserWarning):
+ self._test_basic_auth(opener, auth_handler, "Authorization",
+ realm, http_handler, password_manager,
+ "http://acme.example.com/protected",
+ "http://acme.example.com/protected",
+ )
+
def test_proxy_basic_auth(self):
opener = OpenerDirector()
ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 8af5065..de85bf9 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -526,12 +526,19 @@ class Misc:
The type keyword specifies the form in which the data is
to be returned and should be an atom name such as STRING
- or FILE_NAME. Type defaults to STRING.
+ or FILE_NAME. Type defaults to STRING, except on X11, where the default
+ is to try UTF8_STRING and fall back to STRING.
This command is equivalent to:
selection_get(CLIPBOARD)
"""
+ if 'type' not in kw and self._windowingsystem == 'x11':
+ try:
+ kw['type'] = 'UTF8_STRING'
+ return self.tk.call(('clipboard', 'get') + self._options(kw))
+ except TclError:
+ del kw['type']
return self.tk.call(('clipboard', 'get') + self._options(kw))
def clipboard_clear(self, **kw):
@@ -613,8 +620,16 @@ class Misc:
A keyword parameter selection specifies the name of
the selection and defaults to PRIMARY. A keyword
parameter displayof specifies a widget on the display
- to use."""
+ to use. A keyword parameter type specifies the form of data to be
+ fetched, defaulting to STRING except on X11, where UTF8_STRING is tried
+ before STRING."""
if 'displayof' not in kw: kw['displayof'] = self._w
+ if 'type' not in kw and self._windowingsystem == 'x11':
+ try:
+ kw['type'] = 'UTF8_STRING'
+ return self.tk.call(('selection', 'get') + self._options(kw))
+ except TclError:
+ del kw['type']
return self.tk.call(('selection', 'get') + self._options(kw))
def selection_handle(self, command, **kw):
"""Specify a function COMMAND to call if the X
@@ -1029,6 +1044,15 @@ class Misc:
if displayof is None:
return ('-displayof', self._w)
return ()
+ @property
+ def _windowingsystem(self):
+ """Internal function."""
+ try:
+ return self._root()._windowingsystem_cached
+ except AttributeError:
+ ws = self._root()._windowingsystem_cached = \
+ self.tk.call('tk', 'windowingsystem')
+ return ws
def _options(self, cnf, kw = None):
"""Internal function."""
if kw:
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index fe2cfcd..0035e70 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -95,6 +95,7 @@ import socket
import sys
import time
import collections
+import warnings
from urllib.error import URLError, HTTPError, ContentTooShortError
from urllib.parse import (
@@ -794,7 +795,7 @@ class AbstractBasicAuthHandler:
# allow for double- and single-quoted realm values
# (single quotes are a violation of the RFC, but appear in the wild)
rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+'
- 'realm=(["\'])(.*?)\\2', re.I)
+ 'realm=(["\']?)([^"\']*)\\2', re.I)
# XXX could pre-emptively send auth info already accepted (RFC 2617,
# end of section 2, and section 1.2 immediately after "credentials"
@@ -827,6 +828,9 @@ class AbstractBasicAuthHandler:
mo = AbstractBasicAuthHandler.rx.search(authreq)
if mo:
scheme, quote, realm = mo.groups()
+ if quote not in ["'", '"']:
+ warnings.warn("Basic Auth Realm was unquoted",
+ UserWarning, 2)
if scheme.lower() == 'basic':
response = self.retry_http_basic_auth(host, req, realm)
if response and response.code != 401:
diff --git a/Misc/NEWS b/Misc/NEWS
index 10b5453..08d21f7 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -63,6 +63,18 @@ Core and Builtins
Library
-------
+- Issue #14829: Fix bisect and range() indexing with large indices
+ (>= 2 ** 32) under 64-bit Windows.
+
+- Issue #14777: tkinter may return undecoded UTF-8 bytes as a string when
+ accessing the Tk clipboard. Modify clipboad_get() to first request type
+ UTF8_STRING when no specific type is requested in an X11 windowing
+ environment, falling back to the current default type STRING if that fails.
+ Original patch by Thomas Kluyver.
+
+- Issue #12541: Be lenient with quotes around Realm field of HTTP Basic
+ Authentation in urllib2.
+
- Issue #14662: Prevent shutil failures on OS X when destination does not
support chflag operations. Patch by Hynek Schlawack.
diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c
index 93d0eed..eae2978 100644
--- a/Modules/_bisectmodule.c
+++ b/Modules/_bisectmodule.c
@@ -3,6 +3,7 @@
Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
*/
+#define PY_SSIZE_T_CLEAN
#include "Python.h"
static Py_ssize_t
@@ -192,7 +193,7 @@ insort_left(PyObject *self, PyObject *args, PyObject *kw)
if (PyList_Insert(list, index, item) < 0)
return NULL;
} else {
- result = PyObject_CallMethod(list, "insert", "iO", index, item);
+ result = PyObject_CallMethod(list, "insert", "nO", index, item);
if (result == NULL)
return NULL;
Py_DECREF(result);
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 58d373c..935b205 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -307,7 +307,7 @@ compute_range_item(rangeobject *r, PyObject *arg)
static PyObject *
range_item(rangeobject *r, Py_ssize_t i)
{
- PyObject *res, *arg = PyLong_FromLong(i);
+ PyObject *res, *arg = PyLong_FromSsize_t(i);
if (!arg) {
return NULL;
}
diff --git a/Tools/buildbot/external-common.bat b/Tools/buildbot/external-common.bat
index 2b86c68..5c250f0 100644
--- a/Tools/buildbot/external-common.bat
+++ b/Tools/buildbot/external-common.bat
@@ -23,9 +23,6 @@ if not exist bzip2-1.0.6 (
svn export http://svn.python.org/projects/external/bzip2-1.0.6
)
-@rem Sleepycat db
-if not exist db-4.4.20 svn export http://svn.python.org/projects/external/db-4.4.20-vs9 db-4.4.20
-
@rem OpenSSL
if not exist openssl-1.0.0a svn export http://svn.python.org/projects/external/openssl-1.0.0a