Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit bb9ccc6

Browse files
author
Anselm Kruis
committed
Merge branch master into master-slp
2 parents 197dace + 1b8be1f commit bb9ccc6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+707
-444
lines changed

Doc/faq/programming.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,8 @@ analogue of lisp car is ``lisp_list[0]`` and the analogue of cdr is
11641164
usually a lot slower than using Python lists.
11651165

11661166

1167+
.. _faq-multidimensional-list:
1168+
11671169
How do I create a multidimensional list?
11681170
----------------------------------------
11691171

Doc/library/datetime.rst

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,10 +1734,7 @@ made to civil time.
17341734
otherwise :exc:`ValueError` is raised.
17351735

17361736
The *name* argument is optional. If specified it must be a string that
1737-
is used as the value returned by the ``tzname(dt)`` method. Otherwise,
1738-
``tzname(dt)`` returns a string 'UTCsHH:MM', where s is the sign of
1739-
*offset*, HH and MM are two digits of ``offset.hours`` and
1740-
``offset.minutes`` respectively.
1737+
will be used as the value returned by the :meth:`datetime.tzname` method.
17411738

17421739
.. versionadded:: 3.2
17431740

@@ -1750,11 +1747,19 @@ made to civil time.
17501747

17511748
.. method:: timezone.tzname(dt)
17521749

1753-
Return the fixed value specified when the :class:`timezone` instance is
1754-
constructed or a string 'UTCsHH:MM', where s is the sign of
1755-
*offset*, HH and MM are two digits of ``offset.hours`` and
1750+
Return the fixed value specified when the :class:`timezone` instance
1751+
is constructed. If *name* is not provided in the constructor, the
1752+
name returned by ``tzname(dt)`` is generated from the value of the
1753+
``offset`` as follows. If *offset* is ``timedelta(0)``, the name
1754+
is "UTC", otherwise it is a string 'UTC±HH:MM', where ± is the sign
1755+
of ``offset``, HH and MM are two digits of ``offset.hours`` and
17561756
``offset.minutes`` respectively.
17571757

1758+
.. versionchanged:: 3.6
1759+
Name generated from ``offset=timedelta(0)`` is now plain 'UTC', not
1760+
'UTC+00:00'.
1761+
1762+
17581763
.. method:: timezone.dst(dt)
17591764

17601765
Always returns ``None``.

Doc/library/stdtypes.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -854,8 +854,8 @@ operations have the same priority as the corresponding numeric operations.
854854
| ``s + t`` | the concatenation of *s* and | (6)(7) |
855855
| | *t* | |
856856
+--------------------------+--------------------------------+----------+
857-
| ``s * n`` or | *n* shallow copies of *s* | (2)(7) |
858-
| ``n * s`` | concatenated | |
857+
| ``s * n`` or | equivalent to adding *s* to | (2)(7) |
858+
| ``n * s`` | itself *n* times | |
859859
+--------------------------+--------------------------------+----------+
860860
| ``s[i]`` | *i*\ th item of *s*, origin 0 | \(3) |
861861
+--------------------------+--------------------------------+----------+
@@ -897,9 +897,9 @@ Notes:
897897

898898
(2)
899899
Values of *n* less than ``0`` are treated as ``0`` (which yields an empty
900-
sequence of the same type as *s*). Note also that the copies are shallow;
901-
nested structures are not copied. This often haunts new Python programmers;
902-
consider::
900+
sequence of the same type as *s*). Note that items in the sequence *s*
901+
are not copied; they are referenced multiple times. This often haunts
902+
new Python programmers; consider::
903903

904904
>>> lists = [[]] * 3
905905
>>> lists
@@ -909,7 +909,7 @@ Notes:
909909
[[3], [3], [3]]
910910

911911
What has happened is that ``[[]]`` is a one-element list containing an empty
912-
list, so all three elements of ``[[]] * 3`` are (pointers to) this single empty
912+
list, so all three elements of ``[[]] * 3`` are references to this single empty
913913
list. Modifying any of the elements of ``lists`` modifies this single list.
914914
You can create a list of different lists this way::
915915

@@ -920,6 +920,9 @@ Notes:
920920
>>> lists
921921
[[3], [5], [7]]
922922

923+
Further explanation is available in the FAQ entry
924+
:ref:`faq-multidimensional-list`.
925+
923926
(3)
924927
If *i* or *j* is negative, the index is relative to the end of the string:
925928
``len(s) + i`` or ``len(s) + j`` is substituted. But note that ``-0`` is

Doc/library/subprocess.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ Return code handling translates as follows::
10681068
if rc is not None and rc >> 8:
10691069
print("There were some errors")
10701070
==>
1071-
process = Popen(cmd, 'w', stdin=PIPE)
1071+
process = Popen(cmd, stdin=PIPE)
10721072
...
10731073
process.stdin.close()
10741074
if process.wait() != 0:

Doc/tools/susp-ignored.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,6 @@ library/xml.etree.elementtree,332,:character,"for char in actor.findall('role:ch
288288
library/zipapp,31,:main,"$ python -m zipapp myapp -m ""myapp:main"""
289289
library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a"
290290
library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing"
291-
library/stdtypes,3767,::,>>> m[::2].tolist()
291+
library/stdtypes,,::,>>> m[::2].tolist()
292292
library/sys,1115,`,# ``wrapper`` creates a ``wrap(coro)`` coroutine:
293293
tutorial/venv,77,:c7b9645a6f35,"Python 3.4.3+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)"

Lib/datetime.py

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,48 +1374,42 @@ def tzinfo(self):
13741374
return self._tzinfo
13751375

13761376
@classmethod
1377-
def fromtimestamp(cls, t, tz=None):
1377+
def _fromtimestamp(cls, t, utc, tz):
13781378
"""Construct a datetime from a POSIX timestamp (like time.time()).
13791379
13801380
A timezone info object may be passed in as well.
13811381
"""
1382-
_check_tzinfo_arg(tz)
1383-
1384-
converter = _time.localtime if tz is None else _time.gmtime
1385-
1386-
t, frac = divmod(t, 1.0)
1382+
frac, t = _math.modf(t)
13871383
us = _round_half_up(frac * 1e6)
1388-
1389-
# If timestamp is less than one microsecond smaller than a
1390-
# full second, us can be rounded up to 1000000. In this case,
1391-
# roll over to seconds, otherwise, ValueError is raised
1392-
# by the constructor.
1393-
if us == 1000000:
1384+
if us >= 1000000:
13941385
t += 1
1395-
us = 0
1386+
us -= 1000000
1387+
elif us < 0:
1388+
t -= 1
1389+
us += 1000000
1390+
1391+
converter = _time.gmtime if utc else _time.localtime
13961392
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
13971393
ss = min(ss, 59) # clamp out leap seconds if the platform has them
1398-
result = cls(y, m, d, hh, mm, ss, us, tz)
1394+
return cls(y, m, d, hh, mm, ss, us, tz)
1395+
1396+
@classmethod
1397+
def fromtimestamp(cls, t, tz=None):
1398+
"""Construct a datetime from a POSIX timestamp (like time.time()).
1399+
1400+
A timezone info object may be passed in as well.
1401+
"""
1402+
_check_tzinfo_arg(tz)
1403+
1404+
result = cls._fromtimestamp(t, tz is not None, tz)
13991405
if tz is not None:
14001406
result = tz.fromutc(result)
14011407
return result
14021408

14031409
@classmethod
14041410
def utcfromtimestamp(cls, t):
14051411
"""Construct a naive UTC datetime from a POSIX timestamp."""
1406-
t, frac = divmod(t, 1.0)
1407-
us = _round_half_up(frac * 1e6)
1408-
1409-
# If timestamp is less than one microsecond smaller than a
1410-
# full second, us can be rounded up to 1000000. In this case,
1411-
# roll over to seconds, otherwise, ValueError is raised
1412-
# by the constructor.
1413-
if us == 1000000:
1414-
t += 1
1415-
us = 0
1416-
y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
1417-
ss = min(ss, 59) # clamp out leap seconds if the platform has them
1418-
return cls(y, m, d, hh, mm, ss, us)
1412+
return cls._fromtimestamp(t, True, None)
14191413

14201414
@classmethod
14211415
def now(cls, tz=None):
@@ -1926,6 +1920,8 @@ def fromutc(self, dt):
19261920

19271921
@staticmethod
19281922
def _name_from_offset(delta):
1923+
if not delta:
1924+
return 'UTC'
19291925
if delta < timedelta(0):
19301926
sign = '-'
19311927
delta = -delta

Lib/html/parser.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,15 @@ def goahead(self, end):
139139
if self.convert_charrefs and not self.cdata_elem:
140140
j = rawdata.find('<', i)
141141
if j < 0:
142-
if not end:
142+
# if we can't find the next <, either we are at the end
143+
# or there's more text incoming. If the latter is True,
144+
# we can't pass the text to handle_data in case we have
145+
# a charref cut in half at end. Try to determine if
146+
# this is the case before proceding by looking for an
147+
# & near the end and see if it's followed by a space or ;.
148+
amppos = rawdata.rfind('&', max(i, n-34))
149+
if (amppos >= 0 and
150+
not re.compile(r'[\s;]').search(rawdata, amppos)):
143151
break # wait till we get all the text
144152
j = n
145153
else:

Lib/pdb.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,9 @@ def main():
16691669
# In most cases SystemExit does not warrant a post-mortem session.
16701670
print("The program exited via sys.exit(). Exit status:", end=' ')
16711671
print(sys.exc_info()[1])
1672+
except SyntaxError:
1673+
traceback.print_exc()
1674+
sys.exit(1)
16721675
except:
16731676
traceback.print_exc()
16741677
print("Uncaught exception. Entering post mortem debugging")

Lib/test/datetimetester.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ def test_dst(self):
258258
with self.assertRaises(TypeError): self.EST.dst(5)
259259

260260
def test_tzname(self):
261-
self.assertEqual('UTC+00:00', timezone(ZERO).tzname(None))
261+
self.assertEqual('UTC', timezone.utc.tzname(None))
262+
self.assertEqual('UTC', timezone(ZERO).tzname(None))
262263
self.assertEqual('UTC-05:00', timezone(-5 * HOUR).tzname(None))
263264
self.assertEqual('UTC+09:30', timezone(9.5 * HOUR).tzname(None))
264265
self.assertEqual('UTC-00:01', timezone(timedelta(minutes=-1)).tzname(None))
@@ -668,6 +669,8 @@ def test_microsecond_rounding(self):
668669
eq(td(milliseconds=-0.6/1000), td(microseconds=-1))
669670
eq(td(seconds=0.5/10**6), td(microseconds=1))
670671
eq(td(seconds=-0.5/10**6), td(microseconds=-1))
672+
eq(td(seconds=1/2**7), td(microseconds=7813))
673+
eq(td(seconds=-1/2**7), td(microseconds=-7813))
671674

672675
# Rounding due to contributions from more than one field.
673676
us_per_hour = 3600e6
@@ -1842,8 +1845,8 @@ def test_timestamp_aware(self):
18421845
18000 + 3600 + 2*60 + 3 + 4*1e-6)
18431846

18441847
def test_microsecond_rounding(self):
1845-
for fts in [self.theclass.fromtimestamp,
1846-
self.theclass.utcfromtimestamp]:
1848+
for fts in (datetime.fromtimestamp,
1849+
self.theclass.utcfromtimestamp):
18471850
zero = fts(0)
18481851
self.assertEqual(zero.second, 0)
18491852
self.assertEqual(zero.microsecond, 0)
@@ -1863,6 +1866,9 @@ def test_microsecond_rounding(self):
18631866
self.assertEqual(t, minus_one)
18641867
t = fts(-1e-7)
18651868
self.assertEqual(t, zero)
1869+
t = fts(-1/2**7)
1870+
self.assertEqual(t.second, 59)
1871+
self.assertEqual(t.microsecond, 992187)
18661872

18671873
t = fts(1e-7)
18681874
self.assertEqual(t, zero)
@@ -1874,6 +1880,9 @@ def test_microsecond_rounding(self):
18741880
t = fts(0.9999999)
18751881
self.assertEqual(t.second, 1)
18761882
self.assertEqual(t.microsecond, 0)
1883+
t = fts(1/2**7)
1884+
self.assertEqual(t.second, 0)
1885+
self.assertEqual(t.microsecond, 7813)
18771886

18781887
def test_insane_fromtimestamp(self):
18791888
# It's possible that some platform maps time_t to double,

Lib/test/test_descr.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,51 @@ class SubType(types.ModuleType):
10361036
self.assertTrue(m.__class__ is types.ModuleType)
10371037
self.assertFalse(hasattr(m, "a"))
10381038

1039+
# Make sure that builtin immutable objects don't support __class__
1040+
# assignment, because the object instances may be interned.
1041+
# We set __slots__ = () to ensure that the subclasses are
1042+
# memory-layout compatible, and thus otherwise reasonable candidates
1043+
# for __class__ assignment.
1044+
1045+
# The following types have immutable instances, but are not
1046+
# subclassable and thus don't need to be checked:
1047+
# NoneType, bool
1048+
1049+
class MyInt(int):
1050+
__slots__ = ()
1051+
with self.assertRaises(TypeError):
1052+
(1).__class__ = MyInt
1053+
1054+
class MyFloat(float):
1055+
__slots__ = ()
1056+
with self.assertRaises(TypeError):
1057+
(1.0).__class__ = MyFloat
1058+
1059+
class MyComplex(complex):
1060+
__slots__ = ()
1061+
with self.assertRaises(TypeError):
1062+
(1 + 2j).__class__ = MyComplex
1063+
1064+
class MyStr(str):
1065+
__slots__ = ()
1066+
with self.assertRaises(TypeError):
1067+
"a".__class__ = MyStr
1068+
1069+
class MyBytes(bytes):
1070+
__slots__ = ()
1071+
with self.assertRaises(TypeError):
1072+
b"a".__class__ = MyBytes
1073+
1074+
class MyTuple(tuple):
1075+
__slots__ = ()
1076+
with self.assertRaises(TypeError):
1077+
().__class__ = MyTuple
1078+
1079+
class MyFrozenSet(frozenset):
1080+
__slots__ = ()
1081+
with self.assertRaises(TypeError):
1082+
frozenset().__class__ = MyFrozenSet
1083+
10391084
def test_slots(self):
10401085
# Testing __slots__...
10411086
class C0(object):

Lib/test/test_gdb.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ def get_gdb_version():
3636
# Regex to parse:
3737
# 'GNU gdb (GDB; SUSE Linux Enterprise 12) 7.7\n' -> 7.7
3838
# 'GNU gdb (GDB) Fedora 7.9.1-17.fc22\n' -> 7.9
39-
# 'GNU gdb 6.1.1 [FreeBSD]\n'
40-
match = re.search("^GNU gdb.*? (\d+)\.(\d)", version)
39+
# 'GNU gdb 6.1.1 [FreeBSD]\n' -> 6.1
40+
# 'GNU gdb (GDB) Fedora (7.5.1-37.fc18)\n' -> 7.5
41+
match = re.search(r"^GNU gdb.*?\b(\d+)\.(\d)", version)
4142
if match is None:
4243
raise Exception("unable to parse GDB version: %r" % version)
4344
return (version, int(match.group(1)), int(match.group(2)))

Lib/test/test_glob.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,7 @@ def test_recursive_glob(self):
242242
('a', 'bcd', 'EF'), ('a', 'bcd', 'efg')))
243243
eq(self.rglob('a', '**', 'bcd'), self.joins(('a', 'bcd')))
244244

245-
predir = os.path.abspath(os.curdir)
246-
try:
247-
os.chdir(self.tempdir)
245+
with change_cwd(self.tempdir):
248246
join = os.path.join
249247
eq(glob.glob('**', recursive=True), [join(*i) for i in full])
250248
eq(glob.glob(join('**', ''), recursive=True),
@@ -256,8 +254,6 @@ def test_recursive_glob(self):
256254
if can_symlink():
257255
expect += [join('sym3', 'EF')]
258256
eq(glob.glob(join('**', 'EF'), recursive=True), expect)
259-
finally:
260-
os.chdir(predir)
261257

262258

263259
@skip_unless_symlink

Lib/test/test_htmlparser.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ def handle_starttag(self, tag, attrs):
7272

7373
class EventCollectorCharrefs(EventCollector):
7474

75-
def get_events(self):
76-
return self.events
77-
7875
def handle_charref(self, data):
7976
self.fail('This should never be called with convert_charrefs=True')
8077

@@ -633,6 +630,18 @@ def test_broken_condcoms(self):
633630
]
634631
self._run_check(html, expected)
635632

633+
def test_convert_charrefs_dropped_text(self):
634+
# #23144: make sure that all the events are triggered when
635+
# convert_charrefs is True, even if we don't call .close()
636+
parser = EventCollector(convert_charrefs=True)
637+
# before the fix, bar & baz was missing
638+
parser.feed("foo <a>link</a> bar &amp; baz")
639+
self.assertEqual(
640+
parser.get_events(),
641+
[('data', 'foo '), ('starttag', 'a', []), ('data', 'link'),
642+
('endtag', 'a'), ('data', ' bar & baz')]
643+
)
644+
636645

637646
class AttributesTestCase(TestCaseBase):
638647

0 commit comments

Comments
 (0)