From python-checkins at python.org Sat Aug 1 04:36:11 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 02:36:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150801023611.29410.9710@psf.io> https://hg.python.org/cpython/rev/91c613d04698 changeset: 97177:91c613d04698 parent: 97173:74fc1af57c72 parent: 97176:7ce13edf8b0b user: Terry Jan Reedy date: Fri Jul 31 22:35:15 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/PyShell.py | 13 ++++++------- Lib/idlelib/ScriptBinding.py | 2 +- Misc/ACKS | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -469,7 +469,7 @@ self.poll_subprocess() return self.rpcclt - def restart_subprocess(self, with_cwd=False): + def restart_subprocess(self, with_cwd=False, filename=''): if self.restarting: return self.rpcclt self.restarting = True @@ -497,14 +497,13 @@ console.stop_readline() # annotate restart in shell window and mark it console.text.delete("iomark", "end-1c") - if was_executing: - console.write('\n') - console.showprompt() - halfbar = ((int(console.width) - 16) // 2) * '=' - console.write(halfbar + ' RESTART ' + halfbar) + tag = 'RUN ' + filename if filename else 'RESTART Shell' + halfbar = ((int(console.width) -len(tag) - 4) // 2) * '=' + console.write("\n{0} {1} {0}".format(halfbar, tag)) console.text.mark_set("restart", "end-1c") console.text.mark_gravity("restart", "left") - console.showprompt() + if not filename: + console.showprompt() # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -142,7 +142,7 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False) + interp.restart_subprocess(with_cwd=False, filename=code.co_filename) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1443,6 +1443,7 @@ Doobee R. Tzeck Eren T?rkay Lionel Ulmer +Adnan Umer Roger Upole Daniel Urban Michael Urman -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 04:36:11 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 02:36:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150801023611.1381.60765@psf.io> https://hg.python.org/cpython/rev/7ce13edf8b0b changeset: 97176:7ce13edf8b0b branch: 3.5 parent: 97172:743b3058295d parent: 97175:2ae12789dcb8 user: Terry Jan Reedy date: Fri Jul 31 22:35:00 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/PyShell.py | 13 ++++++------- Lib/idlelib/ScriptBinding.py | 2 +- Misc/ACKS | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -469,7 +469,7 @@ self.poll_subprocess() return self.rpcclt - def restart_subprocess(self, with_cwd=False): + def restart_subprocess(self, with_cwd=False, filename=''): if self.restarting: return self.rpcclt self.restarting = True @@ -497,14 +497,13 @@ console.stop_readline() # annotate restart in shell window and mark it console.text.delete("iomark", "end-1c") - if was_executing: - console.write('\n') - console.showprompt() - halfbar = ((int(console.width) - 16) // 2) * '=' - console.write(halfbar + ' RESTART ' + halfbar) + tag = 'RUN ' + filename if filename else 'RESTART Shell' + halfbar = ((int(console.width) -len(tag) - 4) // 2) * '=' + console.write("\n{0} {1} {0}".format(halfbar, tag)) console.text.mark_set("restart", "end-1c") console.text.mark_gravity("restart", "left") - console.showprompt() + if not filename: + console.showprompt() # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -142,7 +142,7 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False) + interp.restart_subprocess(with_cwd=False, filename=code.co_filename) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1442,6 +1442,7 @@ Doobee R. Tzeck Eren T?rkay Lionel Ulmer +Adnan Umer Roger Upole Daniel Urban Michael Urman -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 04:36:11 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 02:36:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxMTky?= =?utf-8?q?=3A_Idle_Editor=2E_When_a_file_is_run=2C_put_its_name_in_the_re?= =?utf-8?q?start_bar=2E?= Message-ID: <20150801023610.5535.44943@psf.io> https://hg.python.org/cpython/rev/20a8e5dccf66 changeset: 97174:20a8e5dccf66 branch: 2.7 parent: 97159:8203fc75b3d2 user: Terry Jan Reedy date: Fri Jul 31 22:34:31 2015 -0400 summary: Issue #21192: Idle Editor. When a file is run, put its name in the restart bar. Do not print false prompts. Original patch by Adnan Umer. files: Lib/idlelib/PyShell.py | 13 ++++++------- Lib/idlelib/ScriptBinding.py | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -482,7 +482,7 @@ self.poll_subprocess() return self.rpcclt - def restart_subprocess(self, with_cwd=False): + def restart_subprocess(self, with_cwd=False, filename=''): if self.restarting: return self.rpcclt self.restarting = True @@ -510,14 +510,13 @@ console.stop_readline() # annotate restart in shell window and mark it console.text.delete("iomark", "end-1c") - if was_executing: - console.write('\n') - console.showprompt() - halfbar = ((int(console.width) - 16) // 2) * '=' - console.write(halfbar + ' RESTART ' + halfbar) + tag = 'RUN ' + filename if filename else 'RESTART Shell' + halfbar = ((int(console.width) -len(tag) - 4) // 2) * '=' + console.write("\n{0} {1} {0}".format(halfbar, tag)) console.text.mark_set("restart", "end-1c") console.text.mark_gravity("restart", "left") - console.showprompt() + if not filename: + console.showprompt() # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -147,7 +147,7 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False) + interp.restart_subprocess(with_cwd=False, filename=code.co_filename) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 04:36:11 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 02:36:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxMTky?= =?utf-8?q?=3A_Idle_Editor=2E_When_a_file_is_run=2C_put_its_name_in_the_re?= =?utf-8?q?start_bar=2E?= Message-ID: <20150801023610.53987.44227@psf.io> https://hg.python.org/cpython/rev/2ae12789dcb8 changeset: 97175:2ae12789dcb8 branch: 3.4 parent: 97171:6703ac68bf49 user: Terry Jan Reedy date: Fri Jul 31 22:34:37 2015 -0400 summary: Issue #21192: Idle Editor. When a file is run, put its name in the restart bar. Do not print false prompts. Original patch by Adnan Umer. files: Lib/idlelib/PyShell.py | 13 ++++++------- Lib/idlelib/ScriptBinding.py | 2 +- Misc/ACKS | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -469,7 +469,7 @@ self.poll_subprocess() return self.rpcclt - def restart_subprocess(self, with_cwd=False): + def restart_subprocess(self, with_cwd=False, filename=''): if self.restarting: return self.rpcclt self.restarting = True @@ -497,14 +497,13 @@ console.stop_readline() # annotate restart in shell window and mark it console.text.delete("iomark", "end-1c") - if was_executing: - console.write('\n') - console.showprompt() - halfbar = ((int(console.width) - 16) // 2) * '=' - console.write(halfbar + ' RESTART ' + halfbar) + tag = 'RUN ' + filename if filename else 'RESTART Shell' + halfbar = ((int(console.width) -len(tag) - 4) // 2) * '=' + console.write("\n{0} {1} {0}".format(halfbar, tag)) console.text.mark_set("restart", "end-1c") console.text.mark_gravity("restart", "left") - console.showprompt() + if not filename: + console.showprompt() # restart subprocess debugger if debug: # Restarted debugger connects to current instance of debug GUI diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -142,7 +142,7 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False) + interp.restart_subprocess(with_cwd=False, filename=code.co_filename) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1403,6 +1403,7 @@ Doobee R. Tzeck Eren T?rkay Lionel Ulmer +Adnan Umer Roger Upole Daniel Urban Michael Urman -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat Aug 1 10:44:26 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 01 Aug 2015 08:44:26 +0000 Subject: [Python-checkins] Daily reference leaks (91c613d04698): sum=4 Message-ID: <20150801084426.94776.99088@psf.io> results for 91c613d04698 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogkPn0HP', '--timeout', '7200'] From python-checkins at python.org Sat Aug 1 18:53:08 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 01 Aug 2015 16:53:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324762=3A__Speed-u?= =?utf-8?q?p_frozenset=5Fhash=28=29_and_greatly_beef-up_the_comments=2E?= Message-ID: <20150801165307.110834.48774@psf.io> https://hg.python.org/cpython/rev/cf707dd190a9 changeset: 97178:cf707dd190a9 user: Raymond Hettinger date: Sat Aug 01 09:53:00 2015 -0700 summary: Issue #24762: Speed-up frozenset_hash() and greatly beef-up the comments. files: Objects/setobject.c | 70 ++++++++++++++++++++------------ 1 files changed, 43 insertions(+), 27 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -739,41 +739,57 @@ return 0; } +/* Work to increase the bit dispersion for closely spaced hash values. + This is important because some use cases have many combinations of a + small number of elements with nearby hashes so that many distinct + combinations collapse to only a handful of distinct hash values. */ + +static Py_uhash_t +_shuffle_bits(Py_uhash_t h) +{ + return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL; +} + +/* Most of the constants in this hash algorithm are randomly chosen + large primes with "interesting bit patterns" and that passed tests + for good collision statistics on a variety of problematic datasets + including powersets and graph structures (such as David Eppstein's + graph recipes in Lib/test/test_set.py) */ + static Py_hash_t frozenset_hash(PyObject *self) { - /* Most of the constants in this hash algorithm are randomly choosen - large primes with "interesting bit patterns" and that passed - tests for good collision statistics on a variety of problematic - datasets such as: + PySetObject *so = (PySetObject *)self; + Py_uhash_t hash = 1927868237UL; + setentry *entry; - ps = [] - for r in range(21): - ps += itertools.combinations(range(20), r) - num_distinct_hashes = len({hash(frozenset(s)) for s in ps}) + /* Make hash(frozenset({0})) distinct from hash(frozenset()) */ + hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1; - */ - PySetObject *so = (PySetObject *)self; - Py_uhash_t h, hash = 1927868237UL; - setentry *entry; - Py_ssize_t pos = 0; + /* Xor-in shuffled bits from every entry's hash field because xor is + commutative and a frozenset hash should be independent of order. - if (so->hash != -1) - return so->hash; + For speed, include null entries and dummy entries and then + subtract out their effect afterwards so that the final hash + depends only on active entries. This allows the code to be + vectorized by the compiler and it saves the unpredictable + branches that would arise when trying to exclude null and dummy + entries on every iteration. */ - hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1; - while (set_next(so, &pos, &entry)) { - /* Work to increase the bit dispersion for closely spaced hash - values. This is important because some use cases have many - combinations of a small number of elements with nearby - hashes so that many distinct combinations collapse to only - a handful of distinct hash values. */ - h = entry->hash; - hash ^= ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL; - } - /* Make the final result spread-out in a different pattern - than the algorithm for tuples or other python objects. */ + for (entry = so->table; entry <= &so->table[so->mask]; entry++) + hash ^= _shuffle_bits(entry->hash); + + /* Remove the effect of an odd number NULL entries */ + if ((so->mask + 1 - so->fill) & 1) + hash ^= _shuffle_bits(0); + + /* Remove the effect of an odd number of dummy entries */ + if ((so->fill - so->used) & 1) + hash ^= _shuffle_bits(-1); + + /* Disperse patterns arising in nested frozensets */ hash = hash * 69069U + 907133923UL; + if (hash == (Py_uhash_t)-1) hash = 590923713UL; so->hash = hash; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 19:57:57 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 01 Aug 2015 17:57:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Tweak_the_comments?= Message-ID: <20150801175757.110661.18078@psf.io> https://hg.python.org/cpython/rev/0ad74e03e1b5 changeset: 97179:0ad74e03e1b5 user: Raymond Hettinger date: Sat Aug 01 10:57:42 2015 -0700 summary: Tweak the comments files: Objects/setobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -763,7 +763,7 @@ Py_uhash_t hash = 1927868237UL; setentry *entry; - /* Make hash(frozenset({0})) distinct from hash(frozenset()) */ + /* Initial dispersion based on the number of active entries */ hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1; /* Xor-in shuffled bits from every entry's hash field because xor is @@ -790,8 +790,10 @@ /* Disperse patterns arising in nested frozensets */ hash = hash * 69069U + 907133923UL; + /* -1 is reserved as an error code */ if (hash == (Py_uhash_t)-1) hash = 590923713UL; + so->hash = hash; return hash; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 20:07:24 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 01 Aug 2015 18:07:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_comment_typo?= Message-ID: <20150801180724.29418.6693@psf.io> https://hg.python.org/cpython/rev/f6a3310d3cc9 changeset: 97180:f6a3310d3cc9 user: Raymond Hettinger date: Sat Aug 01 11:07:11 2015 -0700 summary: Fix comment typo files: Objects/setobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -779,7 +779,7 @@ for (entry = so->table; entry <= &so->table[so->mask]; entry++) hash ^= _shuffle_bits(entry->hash); - /* Remove the effect of an odd number NULL entries */ + /* Remove the effect of an odd number of NULL entries */ if ((so->mask + 1 - so->fill) & 1) hash ^= _shuffle_bits(0); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 22:20:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 01 Aug 2015 20:20:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogZG9jczogRml4IHBy?= =?utf-8?q?oductionlist_for_async_def_functions?= Message-ID: <20150801202003.5537.93806@psf.io> https://hg.python.org/cpython/rev/78c6149f5a4b changeset: 97181:78c6149f5a4b branch: 3.5 parent: 97176:7ce13edf8b0b user: Yury Selivanov date: Sat Aug 01 16:19:36 2015 -0400 summary: docs: Fix productionlist for async def functions files: Doc/reference/compound_stmts.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -675,7 +675,7 @@ ----------------------------- .. productionlist:: - async_funcdef: "async" `funcdef` + async_funcdef: [`decorators`] "async" "def" `funcname` "(" [`parameter_list`] ")" ["->" `expression`] ":" `suite` .. index:: keyword: async -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 22:20:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 01 Aug 2015 20:20:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150801202003.29396.81539@psf.io> https://hg.python.org/cpython/rev/d8c6673f09ef changeset: 97182:d8c6673f09ef parent: 97180:f6a3310d3cc9 parent: 97181:78c6149f5a4b user: Yury Selivanov date: Sat Aug 01 16:19:49 2015 -0400 summary: Merge 3.5 files: Doc/reference/compound_stmts.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -675,7 +675,7 @@ ----------------------------- .. productionlist:: - async_funcdef: "async" `funcdef` + async_funcdef: [`decorators`] "async" "def" `funcname` "(" [`parameter_list`] ")" ["->" `expression`] ":" `suite` .. index:: keyword: async -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 1 22:32:54 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 20:32:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxMTky?= =?utf-8?q?=3A_acks_for_2=2E7?= Message-ID: <20150801203254.5511.31856@psf.io> https://hg.python.org/cpython/rev/edf9bfe36ad0 changeset: 97183:edf9bfe36ad0 branch: 2.7 parent: 97174:20a8e5dccf66 user: Terry Jan Reedy date: Sat Aug 01 16:32:27 2015 -0400 summary: Issue #21192: acks for 2.7 files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1388,6 +1388,7 @@ Doobee R. Tzeck Eren T?rkay Lionel Ulmer +Adnan Umer Roger Upole Daniel Urban Michael Urman -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 00:21:47 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 01 Aug 2015 22:21:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Clarify_comments_on_setent?= =?utf-8?q?ry_invariants=2E?= Message-ID: <20150801222147.17711.73309@psf.io> https://hg.python.org/cpython/rev/b6c83e01077d changeset: 97184:b6c83e01077d parent: 97182:d8c6673f09ef user: Raymond Hettinger date: Sat Aug 01 15:21:41 2015 -0700 summary: Clarify comments on setentry invariants. files: Include/setobject.h | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Include/setobject.h b/Include/setobject.h --- a/Include/setobject.h +++ b/Include/setobject.h @@ -10,12 +10,13 @@ /* There are three kinds of entries in the table: -1. Unused: key == NULL -2. Active: key != NULL and key != dummy -3. Dummy: key == dummy +1. Unused: key == NULL and hash == 0 +2. Dummy: key == dummy and hash == -1 +3. Active: key != NULL and key != dummy and hash != -1 -The hash field of Unused slots have no meaning. -The hash field of Dummny slots are set to -1 +The hash field of Unused slots is always zero. + +The hash field of Dummy slots are set to -1 meaning that dummy entries can be detected by either entry->key==dummy or by entry->hash==-1. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 00:59:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 22:59:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQ3NDU6?= =?utf-8?q?_Switch_from_Courier_to_platform-sensitive_TkFixedFont_as_defau?= =?utf-8?q?lt?= Message-ID: <20150801225903.17733.14369@psf.io> https://hg.python.org/cpython/rev/5c992189414f changeset: 97186:5c992189414f branch: 3.4 parent: 97175:2ae12789dcb8 user: Terry Jan Reedy date: Sat Aug 01 18:57:33 2015 -0400 summary: Issue 24745: Switch from Courier to platform-sensitive TkFixedFont as default editor font. This should not affect current customized font selections. Patch by Mark Roseman. files: Lib/idlelib/EditorWindow.py | 17 +-------- Lib/idlelib/config-main.def | 2 +- Lib/idlelib/configDialog.py | 40 ++++++++++++------------ Lib/idlelib/configHandler.py | 27 ++++++++++++++++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -230,13 +230,7 @@ vbar['command'] = text.yview vbar.pack(side=RIGHT, fill=Y) text['yscrollcommand'] = vbar.set - fontWeight = 'normal' - if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): - fontWeight='bold' - text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), - idleConf.GetOption('main', 'EditorWindow', - 'font-size', type='int'), - fontWeight)) + text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text_frame.pack(side=LEFT, fill=BOTH, expand=1) text.pack(side=TOP, fill=BOTH, expand=1) text.focus_set() @@ -797,13 +791,8 @@ def ResetFont(self): "Update the text widgets' font if it is changed" # Called from configDialog.py - fontWeight='normal' - if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): - fontWeight='bold' - self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), - idleConf.GetOption('main','EditorWindow','font-size', - type='int'), - fontWeight)) + + self.text['font'] = idleConf.GetFont(self.root, 'main','EditorWindow') def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -53,7 +53,7 @@ [EditorWindow] width= 80 height= 40 -font= courier +font= TkFixedFont font-size= 10 font-bold= 0 encoding= none diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -465,9 +465,9 @@ return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w', self.VarChanged_fontSize) - self.fontName.trace_variable('w', self.VarChanged_fontName) - self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.fontSize.trace_variable('w', self.VarChanged_font) + self.fontName.trace_variable('w', self.VarChanged_font) + self.fontBold.trace_variable('w', self.VarChanged_font) self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) self.colour.trace_variable('w', self.VarChanged_colour) self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) @@ -484,15 +484,15 @@ self.autoSave.trace_variable('w', self.VarChanged_autoSave) self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self, *params): + def VarChanged_font(self, *params): + '''When one font attribute changes, save them all, as they are + not independent from each other. In particular, when we are + overriding the default font, we need to write out everything. + ''' + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) value = self.fontSize.get() self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - - def VarChanged_fontName(self, *params): - value = self.fontName.get() - self.AddChangedItem('main', 'EditorWindow', 'font', value) - - def VarChanged_fontBold(self, *params): value = self.fontBold.get() self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) @@ -958,24 +958,24 @@ fonts.sort() for font in fonts: self.listFontName.insert(END, font) - configuredFont = idleConf.GetOption( - 'main', 'EditorWindow', 'font', default='courier') - lc_configuredFont = configuredFont.lower() - self.fontName.set(lc_configuredFont) + configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow') + fontName = configuredFont[0].lower() + fontSize = configuredFont[1] + fontBold = configuredFont[2]=='bold' + self.fontName.set(fontName) lc_fonts = [s.lower() for s in fonts] - if lc_configuredFont in lc_fonts: - currentFontIndex = lc_fonts.index(lc_configuredFont) + try: + currentFontIndex = lc_fonts.index(fontName) self.listFontName.see(currentFontIndex) self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) + except ValueError: + pass ##font size dropdown - fontSize = idleConf.GetOption( - 'main', 'EditorWindow', 'font-size', type='int', default='10') self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption( - 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) + self.fontBold.set(fontBold) ##font sample self.SetFontSample() diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -22,6 +22,7 @@ import sys from configparser import ConfigParser +from tkinter.font import Font, nametofont class InvalidConfigType(Exception): pass class InvalidConfigSet(Exception): pass @@ -670,6 +671,32 @@ self.GetExtraHelpSourceList('user') ) return allHelpSources + def GetFont(self, root, configType, section): + """Retrieve a font from configuration (font, font-size, font-bold) + Intercept the special value 'TkFixedFont' and substitute + the actual font, factoring in some tweaks if needed for + appearance sakes. + + The 'root' parameter can normally be any valid Tkinter widget. + + Return a tuple (family, size, weight) suitable for passing + to tkinter.Font + """ + family = self.GetOption(configType, section, 'font', default='courier') + size = self.GetOption(configType, section, 'font-size', type='int', + default='10') + bold = self.GetOption(configType, section, 'font-bold', default=0, + type='bool') + if (family == 'TkFixedFont'): + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' + return (family, size, 'bold' if bold else 'normal') + def LoadCfgFiles(self): "Load all configuration files." for key in self.defaultCfg: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 00:59:03 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 22:59:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgMjQ3NDU6?= =?utf-8?q?_Switch_from_Courier_to_platform-sensitive_TkFixedFont_as_defau?= =?utf-8?q?lt?= Message-ID: <20150801225903.94780.71788@psf.io> https://hg.python.org/cpython/rev/55e5f7766d2c changeset: 97185:55e5f7766d2c branch: 2.7 parent: 97183:edf9bfe36ad0 user: Terry Jan Reedy date: Sat Aug 01 18:57:27 2015 -0400 summary: Issue 24745: Switch from Courier to platform-sensitive TkFixedFont as default editor font. This should not affect current customized font selections. Patch by Mark Roseman. files: Lib/idlelib/EditorWindow.py | 17 +-------- Lib/idlelib/config-main.def | 2 +- Lib/idlelib/configDialog.py | 40 ++++++++++++------------ Lib/idlelib/configHandler.py | 27 ++++++++++++++++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -256,13 +256,7 @@ vbar['command'] = text.yview vbar.pack(side=RIGHT, fill=Y) text['yscrollcommand'] = vbar.set - fontWeight = 'normal' - if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): - fontWeight='bold' - text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), - idleConf.GetOption('main', 'EditorWindow', - 'font-size', type='int'), - fontWeight)) + text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text_frame.pack(side=LEFT, fill=BOTH, expand=1) text.pack(side=TOP, fill=BOTH, expand=1) text.focus_set() @@ -799,13 +793,8 @@ def ResetFont(self): "Update the text widgets' font if it is changed" # Called from configDialog.py - fontWeight='normal' - if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): - fontWeight='bold' - self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), - idleConf.GetOption('main','EditorWindow','font-size', - type='int'), - fontWeight)) + + self.text['font'] = idleConf.GetFont(self.root, 'main','EditorWindow') def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -53,7 +53,7 @@ [EditorWindow] width= 80 height= 40 -font= courier +font= TkFixedFont font-size= 10 font-bold= 0 encoding= none diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -482,9 +482,9 @@ return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w', self.VarChanged_fontSize) - self.fontName.trace_variable('w', self.VarChanged_fontName) - self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.fontSize.trace_variable('w', self.VarChanged_font) + self.fontName.trace_variable('w', self.VarChanged_font) + self.fontBold.trace_variable('w', self.VarChanged_font) self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) self.colour.trace_variable('w', self.VarChanged_colour) self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) @@ -501,15 +501,15 @@ self.autoSave.trace_variable('w', self.VarChanged_autoSave) self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self, *params): + def VarChanged_font(self, *params): + '''When one font attribute changes, save them all, as they are + not independent from each other. In particular, when we are + overriding the default font, we need to write out everything. + ''' + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) value = self.fontSize.get() self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - - def VarChanged_fontName(self, *params): - value = self.fontName.get() - self.AddChangedItem('main', 'EditorWindow', 'font', value) - - def VarChanged_fontBold(self, *params): value = self.fontBold.get() self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) @@ -975,24 +975,24 @@ fonts.sort() for font in fonts: self.listFontName.insert(END, font) - configuredFont = idleConf.GetOption( - 'main', 'EditorWindow', 'font', default='courier') - lc_configuredFont = configuredFont.lower() - self.fontName.set(lc_configuredFont) + configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow') + fontName = configuredFont[0].lower() + fontSize = configuredFont[1] + fontBold = configuredFont[2]=='bold' + self.fontName.set(fontName) lc_fonts = [s.lower() for s in fonts] - if lc_configuredFont in lc_fonts: - currentFontIndex = lc_fonts.index(lc_configuredFont) + try: + currentFontIndex = lc_fonts.index(fontName) self.listFontName.see(currentFontIndex) self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) + except ValueError: + pass ##font size dropdown - fontSize = idleConf.GetOption( - 'main', 'EditorWindow', 'font-size', type='int', default='10') self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption( - 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) + self.fontBold.set(fontBold) ##font sample self.SetFontSample() diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -23,6 +23,7 @@ import sys from ConfigParser import ConfigParser +from tkFont import Font, nametofont class InvalidConfigType(Exception): pass class InvalidConfigSet(Exception): pass @@ -671,6 +672,32 @@ self.GetExtraHelpSourceList('user') ) return allHelpSources + def GetFont(self, root, configType, section): + """Retrieve a font from configuration (font, font-size, font-bold) + Intercept the special value 'TkFixedFont' and substitute + the actual font, factoring in some tweaks if needed for + appearance sakes. + + The 'root' parameter can normally be any valid Tkinter widget. + + Return a tuple (family, size, weight) suitable for passing + to tkinter.Font + """ + family = self.GetOption(configType, section, 'font', default='courier') + size = self.GetOption(configType, section, 'font-size', type='int', + default='10') + bold = self.GetOption(configType, section, 'font-bold', default=0, + type='bool') + if (family == 'TkFixedFont'): + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' + return (family, size, 'bold' if bold else 'normal') + def LoadCfgFiles(self): "Load all configuration files." for key in self.defaultCfg: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 00:59:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 22:59:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_24745=3A_Merge_with_3=2E4?= Message-ID: <20150801225904.53963.71929@psf.io> https://hg.python.org/cpython/rev/90c02a0bec08 changeset: 97187:90c02a0bec08 branch: 3.5 parent: 97181:78c6149f5a4b parent: 97186:5c992189414f user: Terry Jan Reedy date: Sat Aug 01 18:58:23 2015 -0400 summary: Issue 24745: Merge with 3.4 files: Lib/idlelib/EditorWindow.py | 17 +-------- Lib/idlelib/config-main.def | 2 +- Lib/idlelib/configDialog.py | 40 ++++++++++++------------ Lib/idlelib/configHandler.py | 27 ++++++++++++++++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -230,13 +230,7 @@ vbar['command'] = text.yview vbar.pack(side=RIGHT, fill=Y) text['yscrollcommand'] = vbar.set - fontWeight = 'normal' - if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): - fontWeight='bold' - text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), - idleConf.GetOption('main', 'EditorWindow', - 'font-size', type='int'), - fontWeight)) + text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text_frame.pack(side=LEFT, fill=BOTH, expand=1) text.pack(side=TOP, fill=BOTH, expand=1) text.focus_set() @@ -797,13 +791,8 @@ def ResetFont(self): "Update the text widgets' font if it is changed" # Called from configDialog.py - fontWeight='normal' - if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): - fontWeight='bold' - self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), - idleConf.GetOption('main','EditorWindow','font-size', - type='int'), - fontWeight)) + + self.text['font'] = idleConf.GetFont(self.root, 'main','EditorWindow') def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -53,7 +53,7 @@ [EditorWindow] width= 80 height= 40 -font= courier +font= TkFixedFont font-size= 10 font-bold= 0 encoding= none diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -465,9 +465,9 @@ return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w', self.VarChanged_fontSize) - self.fontName.trace_variable('w', self.VarChanged_fontName) - self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.fontSize.trace_variable('w', self.VarChanged_font) + self.fontName.trace_variable('w', self.VarChanged_font) + self.fontBold.trace_variable('w', self.VarChanged_font) self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) self.colour.trace_variable('w', self.VarChanged_colour) self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) @@ -484,15 +484,15 @@ self.autoSave.trace_variable('w', self.VarChanged_autoSave) self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self, *params): + def VarChanged_font(self, *params): + '''When one font attribute changes, save them all, as they are + not independent from each other. In particular, when we are + overriding the default font, we need to write out everything. + ''' + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) value = self.fontSize.get() self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - - def VarChanged_fontName(self, *params): - value = self.fontName.get() - self.AddChangedItem('main', 'EditorWindow', 'font', value) - - def VarChanged_fontBold(self, *params): value = self.fontBold.get() self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) @@ -958,24 +958,24 @@ fonts.sort() for font in fonts: self.listFontName.insert(END, font) - configuredFont = idleConf.GetOption( - 'main', 'EditorWindow', 'font', default='courier') - lc_configuredFont = configuredFont.lower() - self.fontName.set(lc_configuredFont) + configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow') + fontName = configuredFont[0].lower() + fontSize = configuredFont[1] + fontBold = configuredFont[2]=='bold' + self.fontName.set(fontName) lc_fonts = [s.lower() for s in fonts] - if lc_configuredFont in lc_fonts: - currentFontIndex = lc_fonts.index(lc_configuredFont) + try: + currentFontIndex = lc_fonts.index(fontName) self.listFontName.see(currentFontIndex) self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) + except ValueError: + pass ##font size dropdown - fontSize = idleConf.GetOption( - 'main', 'EditorWindow', 'font-size', type='int', default='10') self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption( - 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) + self.fontBold.set(fontBold) ##font sample self.SetFontSample() diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -22,6 +22,7 @@ import sys from configparser import ConfigParser +from tkinter.font import Font, nametofont class InvalidConfigType(Exception): pass class InvalidConfigSet(Exception): pass @@ -670,6 +671,32 @@ self.GetExtraHelpSourceList('user') ) return allHelpSources + def GetFont(self, root, configType, section): + """Retrieve a font from configuration (font, font-size, font-bold) + Intercept the special value 'TkFixedFont' and substitute + the actual font, factoring in some tweaks if needed for + appearance sakes. + + The 'root' parameter can normally be any valid Tkinter widget. + + Return a tuple (family, size, weight) suitable for passing + to tkinter.Font + """ + family = self.GetOption(configType, section, 'font', default='courier') + size = self.GetOption(configType, section, 'font-size', type='int', + default='10') + bold = self.GetOption(configType, section, 'font-bold', default=0, + type='bool') + if (family == 'TkFixedFont'): + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' + return (family, size, 'bold' if bold else 'normal') + def LoadCfgFiles(self): "Load all configuration files." for key in self.defaultCfg: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 00:59:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 22:59:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_24745=3A_Merge_with_3=2E5?= Message-ID: <20150801225904.23412.52927@psf.io> https://hg.python.org/cpython/rev/3a731756f9cc changeset: 97188:3a731756f9cc parent: 97184:b6c83e01077d parent: 97187:90c02a0bec08 user: Terry Jan Reedy date: Sat Aug 01 18:58:42 2015 -0400 summary: Issue 24745: Merge with 3.5 files: Lib/idlelib/EditorWindow.py | 17 +-------- Lib/idlelib/config-main.def | 2 +- Lib/idlelib/configDialog.py | 40 ++++++++++++------------ Lib/idlelib/configHandler.py | 27 ++++++++++++++++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -230,13 +230,7 @@ vbar['command'] = text.yview vbar.pack(side=RIGHT, fill=Y) text['yscrollcommand'] = vbar.set - fontWeight = 'normal' - if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): - fontWeight='bold' - text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), - idleConf.GetOption('main', 'EditorWindow', - 'font-size', type='int'), - fontWeight)) + text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text_frame.pack(side=LEFT, fill=BOTH, expand=1) text.pack(side=TOP, fill=BOTH, expand=1) text.focus_set() @@ -797,13 +791,8 @@ def ResetFont(self): "Update the text widgets' font if it is changed" # Called from configDialog.py - fontWeight='normal' - if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): - fontWeight='bold' - self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), - idleConf.GetOption('main','EditorWindow','font-size', - type='int'), - fontWeight)) + + self.text['font'] = idleConf.GetFont(self.root, 'main','EditorWindow') def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -53,7 +53,7 @@ [EditorWindow] width= 80 height= 40 -font= courier +font= TkFixedFont font-size= 10 font-bold= 0 encoding= none diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -465,9 +465,9 @@ return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w', self.VarChanged_fontSize) - self.fontName.trace_variable('w', self.VarChanged_fontName) - self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.fontSize.trace_variable('w', self.VarChanged_font) + self.fontName.trace_variable('w', self.VarChanged_font) + self.fontBold.trace_variable('w', self.VarChanged_font) self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) self.colour.trace_variable('w', self.VarChanged_colour) self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) @@ -484,15 +484,15 @@ self.autoSave.trace_variable('w', self.VarChanged_autoSave) self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self, *params): + def VarChanged_font(self, *params): + '''When one font attribute changes, save them all, as they are + not independent from each other. In particular, when we are + overriding the default font, we need to write out everything. + ''' + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) value = self.fontSize.get() self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - - def VarChanged_fontName(self, *params): - value = self.fontName.get() - self.AddChangedItem('main', 'EditorWindow', 'font', value) - - def VarChanged_fontBold(self, *params): value = self.fontBold.get() self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) @@ -958,24 +958,24 @@ fonts.sort() for font in fonts: self.listFontName.insert(END, font) - configuredFont = idleConf.GetOption( - 'main', 'EditorWindow', 'font', default='courier') - lc_configuredFont = configuredFont.lower() - self.fontName.set(lc_configuredFont) + configuredFont = idleConf.GetFont(self, 'main', 'EditorWindow') + fontName = configuredFont[0].lower() + fontSize = configuredFont[1] + fontBold = configuredFont[2]=='bold' + self.fontName.set(fontName) lc_fonts = [s.lower() for s in fonts] - if lc_configuredFont in lc_fonts: - currentFontIndex = lc_fonts.index(lc_configuredFont) + try: + currentFontIndex = lc_fonts.index(fontName) self.listFontName.see(currentFontIndex) self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) + except ValueError: + pass ##font size dropdown - fontSize = idleConf.GetOption( - 'main', 'EditorWindow', 'font-size', type='int', default='10') self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption( - 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) + self.fontBold.set(fontBold) ##font sample self.SetFontSample() diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -22,6 +22,7 @@ import sys from configparser import ConfigParser +from tkinter.font import Font, nametofont class InvalidConfigType(Exception): pass class InvalidConfigSet(Exception): pass @@ -670,6 +671,32 @@ self.GetExtraHelpSourceList('user') ) return allHelpSources + def GetFont(self, root, configType, section): + """Retrieve a font from configuration (font, font-size, font-bold) + Intercept the special value 'TkFixedFont' and substitute + the actual font, factoring in some tweaks if needed for + appearance sakes. + + The 'root' parameter can normally be any valid Tkinter widget. + + Return a tuple (family, size, weight) suitable for passing + to tkinter.Font + """ + family = self.GetOption(configType, section, 'font', default='courier') + size = self.GetOption(configType, section, 'font-size', type='int', + default='10') + bold = self.GetOption(configType, section, 'font-bold', default=0, + type='bool') + if (family == 'TkFixedFont'): + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' + return (family, size, 'bold' if bold else 'normal') + def LoadCfgFiles(self): "Load all configuration files." for key in self.defaultCfg: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 01:16:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 23:16:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgMjQ3NDU6?= =?utf-8?q?_Add_ACKS_entry=2E?= Message-ID: <20150801231604.5515.73465@psf.io> https://hg.python.org/cpython/rev/82198ae039cd changeset: 97189:82198ae039cd branch: 3.4 parent: 97186:5c992189414f user: Terry Jan Reedy date: Sat Aug 01 19:12:37 2015 -0400 summary: Issue 24745: Add ACKS entry. files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1164,6 +1164,7 @@ Case Roole Timothy Roscoe Erik Rose +Mark Roseman Jim Roskind Brian Rosner Guido van Rossum -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 01:16:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 23:16:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150801231604.17731.30773@psf.io> https://hg.python.org/cpython/rev/05cbe6544707 changeset: 97191:05cbe6544707 parent: 97188:3a731756f9cc parent: 97190:bf14b74d6fc0 user: Terry Jan Reedy date: Sat Aug 01 19:15:28 2015 -0400 summary: Merge with 3.5 files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1196,6 +1196,7 @@ Case Roole Timothy Roscoe Erik Rose +Mark Roseman Josh Rosenberg Jim Roskind Brian Rosner -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 01:16:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 23:16:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_24745=3A_Add_ACKS_entry=2E?= Message-ID: <20150801231604.17715.81854@psf.io> https://hg.python.org/cpython/rev/bf14b74d6fc0 changeset: 97190:bf14b74d6fc0 branch: 3.5 parent: 97187:90c02a0bec08 parent: 97189:82198ae039cd user: Terry Jan Reedy date: Sat Aug 01 19:15:11 2015 -0400 summary: Issue 24745: Add ACKS entry. files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1196,6 +1196,7 @@ Case Roole Timothy Roscoe Erik Rose +Mark Roseman Josh Rosenberg Jim Roskind Brian Rosner -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 01:16:04 2015 From: python-checkins at python.org (terry.reedy) Date: Sat, 01 Aug 2015 23:16:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgMjQ3NDU6?= =?utf-8?q?_Add_ACKS_entry=2E?= Message-ID: <20150801231604.94766.21018@psf.io> https://hg.python.org/cpython/rev/5744985ad8dc changeset: 97192:5744985ad8dc branch: 2.7 parent: 97185:55e5f7766d2c user: Terry Jan Reedy date: Sat Aug 01 19:15:37 2015 -0400 summary: Issue 24745: Add ACKS entry. files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1154,6 +1154,7 @@ Case Roole Timothy Roscoe Erik Rose +Mark Roseman Jim Roskind Brian Rosner Guido van Rossum -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 04:39:55 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 02:39:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323652=3A_Merge_with_3=2E4?= Message-ID: <20150802023955.1391.2737@psf.io> https://hg.python.org/cpython/rev/a99f17c752d8 changeset: 97195:a99f17c752d8 branch: 3.5 parent: 97190:bf14b74d6fc0 parent: 97194:c18a18b65a49 user: Zachary Ware date: Sat Aug 01 21:38:04 2015 -0500 summary: Issue #23652: Merge with 3.4 files: Misc/NEWS | 4 ++++ Modules/selectmodule.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Library ------- +- Issue #23652: Make it possible to compile the select module against the + libc headers from the Linux Standard Base, which do not include some + EPOLL macros. Patch by Matt Frank. + - Issue #22932: Fix timezones in email.utils.formatdate. Patch from Dmitry Shachnev. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2479,11 +2479,22 @@ PyModule_AddIntMacro(m, EPOLLONESHOT); #endif /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */ + +#ifdef EPOLLRDNORM PyModule_AddIntMacro(m, EPOLLRDNORM); +#endif +#ifdef EPOLLRDBAND PyModule_AddIntMacro(m, EPOLLRDBAND); +#endif +#ifdef EPOLLWRNORM PyModule_AddIntMacro(m, EPOLLWRNORM); +#endif +#ifdef EPOLLWRBAND PyModule_AddIntMacro(m, EPOLLWRBAND); +#endif +#ifdef EPOLLMSG PyModule_AddIntMacro(m, EPOLLMSG); +#endif #ifdef EPOLL_CLOEXEC PyModule_AddIntMacro(m, EPOLL_CLOEXEC); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 04:39:55 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 02:39:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNjUy?= =?utf-8?q?=3A_Make_the_select_module_compile_against_LSB_headers=2E?= Message-ID: <20150802023955.23390.34498@psf.io> https://hg.python.org/cpython/rev/c18a18b65a49 changeset: 97194:c18a18b65a49 branch: 3.4 parent: 97189:82198ae039cd user: Zachary Ware date: Sat Aug 01 21:34:05 2015 -0500 summary: Issue #23652: Make the select module compile against LSB headers. Patch by Matt Frank. files: Misc/NEWS | 4 ++++ Modules/selectmodule.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,10 @@ Library ------- +- Issue #23652: Make it possible to compile the select module against the + libc headers from the Linux Standard Base, which do not include some + EPOLL macros. Patch by Matt Frank. + - Issue #22932: Fix timezones in email.utils.formatdate. Patch from Dmitry Shachnev. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2372,11 +2372,22 @@ PyModule_AddIntMacro(m, EPOLLONESHOT); #endif /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */ + +#ifdef EPOLLRDNORM PyModule_AddIntMacro(m, EPOLLRDNORM); +#endif +#ifdef EPOLLRDBAND PyModule_AddIntMacro(m, EPOLLRDBAND); +#endif +#ifdef EPOLLWRNORM PyModule_AddIntMacro(m, EPOLLWRNORM); +#endif +#ifdef EPOLLWRBAND PyModule_AddIntMacro(m, EPOLLWRBAND); +#endif +#ifdef EPOLLMSG PyModule_AddIntMacro(m, EPOLLMSG); +#endif #ifdef EPOLL_CLOEXEC PyModule_AddIntMacro(m, EPOLL_CLOEXEC); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 04:39:54 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 02:39:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNjUy?= =?utf-8?q?=3A_Make_the_select_module_compile_against_LSB_headers=2E?= Message-ID: <20150802023954.17723.78480@psf.io> https://hg.python.org/cpython/rev/e38470b49d3c changeset: 97193:e38470b49d3c branch: 2.7 user: Zachary Ware date: Sat Aug 01 21:30:11 2015 -0500 summary: Issue #23652: Make the select module compile against LSB headers. Initial patch by Matt Frank. files: Misc/ACKS | 1 + Misc/NEWS | 4 ++++ Modules/selectmodule.c | 10 ++++++++++ 3 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -429,6 +429,7 @@ Chris Foster John Fouhy Andrew Francis +Matt Frank Stefan Franke Martin Franklin Kent Frazier diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,10 @@ Library ------- +- Issue #23652: Make it possible to compile the select module against the + libc headers from the Linux Standard Base, which do not include some + EPOLL macros. Initial patch by Matt Frank. + - Issue #15138: Speed up base64.urlsafe_b64{en,de}code considerably. - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -1874,11 +1874,21 @@ PyModule_AddIntConstant(m, "EPOLLONESHOT", EPOLLONESHOT); #endif /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */ +#ifdef EPOLLRDNORM PyModule_AddIntConstant(m, "EPOLLRDNORM", EPOLLRDNORM); +#endif +#ifdef EPOLLRDBAND PyModule_AddIntConstant(m, "EPOLLRDBAND", EPOLLRDBAND); +#endif +#ifdef EPOLLWRNORM PyModule_AddIntConstant(m, "EPOLLWRNORM", EPOLLWRNORM); +#endif +#ifdef EPOLLWRBAND PyModule_AddIntConstant(m, "EPOLLWRBAND", EPOLLWRBAND); +#endif +#ifdef EPOLLMSG PyModule_AddIntConstant(m, "EPOLLMSG", EPOLLMSG); +#endif #endif /* HAVE_EPOLL */ #ifdef HAVE_KQUEUE -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 04:39:55 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 02:39:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2323652=3A_Merge_with_3=2E5?= Message-ID: <20150802023955.94768.82598@psf.io> https://hg.python.org/cpython/rev/c7273b46980c changeset: 97196:c7273b46980c parent: 97191:05cbe6544707 parent: 97195:a99f17c752d8 user: Zachary Ware date: Sat Aug 01 21:38:53 2015 -0500 summary: Closes #23652: Merge with 3.5 files: Misc/NEWS | 4 ++++ Modules/selectmodule.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Library ------- +- Issue #23652: Make it possible to compile the select module against the + libc headers from the Linux Standard Base, which do not include some + EPOLL macros. Patch by Matt Frank. + - Issue #22932: Fix timezones in email.utils.formatdate. Patch from Dmitry Shachnev. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2479,11 +2479,22 @@ PyModule_AddIntMacro(m, EPOLLONESHOT); #endif /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */ + +#ifdef EPOLLRDNORM PyModule_AddIntMacro(m, EPOLLRDNORM); +#endif +#ifdef EPOLLRDBAND PyModule_AddIntMacro(m, EPOLLRDBAND); +#endif +#ifdef EPOLLWRNORM PyModule_AddIntMacro(m, EPOLLWRNORM); +#endif +#ifdef EPOLLWRBAND PyModule_AddIntMacro(m, EPOLLWRBAND); +#endif +#ifdef EPOLLMSG PyModule_AddIntMacro(m, EPOLLMSG); +#endif #ifdef EPOLL_CLOEXEC PyModule_AddIntMacro(m, EPOLL_CLOEXEC); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 05:01:25 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 03:01:25 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMTgy?= =?utf-8?q?=3A_PEP8-ify_the_annotation_grammar_tests=2E__Patch_by_Ian_Lee?= =?utf-8?q?=2E?= Message-ID: <20150802030125.29408.76125@psf.io> https://hg.python.org/cpython/rev/c981d9819384 changeset: 97197:c981d9819384 branch: 3.4 parent: 97194:c18a18b65a49 user: Zachary Ware date: Sat Aug 01 21:55:36 2015 -0500 summary: Issue #23182: PEP8-ify the annotation grammar tests. Patch by Ian Lee. files: Lib/test/test_grammar.py | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -302,27 +302,27 @@ # argument annotation tests def f(x) -> list: pass self.assertEqual(f.__annotations__, {'return': list}) - def f(x:int): pass + def f(x: int): pass self.assertEqual(f.__annotations__, {'x': int}) - def f(*x:str): pass + def f(*x: str): pass self.assertEqual(f.__annotations__, {'x': str}) - def f(**x:float): pass + def f(**x: float): pass self.assertEqual(f.__annotations__, {'x': float}) - def f(x, y:1+2): pass + def f(x, y: 1+2): pass self.assertEqual(f.__annotations__, {'y': 3}) - def f(a, b:1, c:2, d): pass + def f(a, b: 1, c: 2, d): pass self.assertEqual(f.__annotations__, {'b': 1, 'c': 2}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6): pass + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): pass self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6, h:7, i=8, j:9=10, - **k:11) -> 12: pass + {'b': 1, 'c': 2, 'e': 3, 'g': 6}) + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10, + **k: 11) -> 12: pass self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, - 'k': 11, 'return': 12}) + {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, + 'k': 11, 'return': 12}) # Check for issue #20625 -- annotations mangling class Spam: - def f(self, *, __kw:1): + def f(self, *, __kw: 1): pass class Ham(Spam): pass self.assertEqual(Spam.f.__annotations__, {'_Spam__kw': 1}) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 05:01:25 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 03:01:25 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323182=3A_Merge_with_3=2E4?= Message-ID: <20150802030125.5521.88884@psf.io> https://hg.python.org/cpython/rev/f35bdb6dd242 changeset: 97198:f35bdb6dd242 branch: 3.5 parent: 97195:a99f17c752d8 parent: 97197:c981d9819384 user: Zachary Ware date: Sat Aug 01 21:57:22 2015 -0500 summary: Issue #23182: Merge with 3.4 files: Lib/test/test_grammar.py | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -308,27 +308,27 @@ # argument annotation tests def f(x) -> list: pass self.assertEqual(f.__annotations__, {'return': list}) - def f(x:int): pass + def f(x: int): pass self.assertEqual(f.__annotations__, {'x': int}) - def f(*x:str): pass + def f(*x: str): pass self.assertEqual(f.__annotations__, {'x': str}) - def f(**x:float): pass + def f(**x: float): pass self.assertEqual(f.__annotations__, {'x': float}) - def f(x, y:1+2): pass + def f(x, y: 1+2): pass self.assertEqual(f.__annotations__, {'y': 3}) - def f(a, b:1, c:2, d): pass + def f(a, b: 1, c: 2, d): pass self.assertEqual(f.__annotations__, {'b': 1, 'c': 2}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6): pass + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): pass self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6, h:7, i=8, j:9=10, - **k:11) -> 12: pass + {'b': 1, 'c': 2, 'e': 3, 'g': 6}) + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10, + **k: 11) -> 12: pass self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, - 'k': 11, 'return': 12}) + {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, + 'k': 11, 'return': 12}) # Check for issue #20625 -- annotations mangling class Spam: - def f(self, *, __kw:1): + def f(self, *, __kw: 1): pass class Ham(Spam): pass self.assertEqual(Spam.f.__annotations__, {'_Spam__kw': 1}) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 05:01:26 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 02 Aug 2015 03:01:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2323182=3A_Merge_with_3=2E5?= Message-ID: <20150802030125.53991.30862@psf.io> https://hg.python.org/cpython/rev/a0ac94514a30 changeset: 97199:a0ac94514a30 parent: 97196:c7273b46980c parent: 97198:f35bdb6dd242 user: Zachary Ware date: Sat Aug 01 22:00:17 2015 -0500 summary: Closes #23182: Merge with 3.5 files: Lib/test/test_grammar.py | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -308,27 +308,27 @@ # argument annotation tests def f(x) -> list: pass self.assertEqual(f.__annotations__, {'return': list}) - def f(x:int): pass + def f(x: int): pass self.assertEqual(f.__annotations__, {'x': int}) - def f(*x:str): pass + def f(*x: str): pass self.assertEqual(f.__annotations__, {'x': str}) - def f(**x:float): pass + def f(**x: float): pass self.assertEqual(f.__annotations__, {'x': float}) - def f(x, y:1+2): pass + def f(x, y: 1+2): pass self.assertEqual(f.__annotations__, {'y': 3}) - def f(a, b:1, c:2, d): pass + def f(a, b: 1, c: 2, d): pass self.assertEqual(f.__annotations__, {'b': 1, 'c': 2}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6): pass + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): pass self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6, h:7, i=8, j:9=10, - **k:11) -> 12: pass + {'b': 1, 'c': 2, 'e': 3, 'g': 6}) + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10, + **k: 11) -> 12: pass self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, - 'k': 11, 'return': 12}) + {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, + 'k': 11, 'return': 12}) # Check for issue #20625 -- annotations mangling class Spam: - def f(self, *, __kw:1): + def f(self, *, __kw: 1): pass class Ham(Spam): pass self.assertEqual(Spam.f.__annotations__, {'_Spam__kw': 1}) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun Aug 2 10:44:04 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 02 Aug 2015 08:44:04 +0000 Subject: [Python-checkins] Daily reference leaks (a0ac94514a30): sum=4 Message-ID: <20150802084404.29394.77216@psf.io> results for a0ac94514a30 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogZ7TnuH', '--timeout', '7200'] From python-checkins at python.org Sun Aug 2 14:21:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 02 Aug 2015 12:21:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320557=3A_Use_specific_asserts_in_io_tests=2E?= Message-ID: <20150802122120.29418.54596@psf.io> https://hg.python.org/cpython/rev/859a45ca1e86 changeset: 97202:859a45ca1e86 parent: 97199:a0ac94514a30 parent: 97201:2453ac990e5b user: Serhiy Storchaka date: Sun Aug 02 15:18:53 2015 +0300 summary: Issue #20557: Use specific asserts in io tests. files: Lib/test/test_bufio.py | 2 +- Lib/test/test_file.py | 4 ++-- Lib/test/test_fileio.py | 6 +++--- Lib/test/test_io.py | 20 ++++++++++---------- Lib/test/test_memoryio.py | 6 ++++-- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_bufio.py b/Lib/test/test_bufio.py --- a/Lib/test/test_bufio.py +++ b/Lib/test/test_bufio.py @@ -34,7 +34,7 @@ line = f.readline() self.assertEqual(line, s) line = f.readline() - self.assertTrue(not line) # Must be at EOF + self.assertFalse(line) # Must be at EOF f.close() finally: support.unlink(support.TESTFN) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -83,8 +83,8 @@ def testErrors(self): f = self.f self.assertEqual(f.name, TESTFN) - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) if hasattr(f, "readinto"): self.assertRaises((OSError, TypeError), f.readinto, "") diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -177,15 +177,15 @@ def testErrors(self): f = self.f - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) #self.assertEqual(f.name, TESTFN) self.assertRaises(ValueError, f.read, 10) # Open for reading f.close() self.assertTrue(f.closed) f = self.FileIO(TESTFN, 'r') self.assertRaises(TypeError, f.readinto, "") - self.assertTrue(not f.closed) + self.assertFalse(f.closed) f.close() self.assertTrue(f.closed) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -449,7 +449,7 @@ with self.open(support.TESTFN, "ab") as f: self.assertEqual(f.tell(), 3) with self.open(support.TESTFN, "a") as f: - self.assertTrue(f.tell() > 0) + self.assertGreater(f.tell(), 0) def test_destructor(self): record = [] @@ -569,7 +569,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"abcxxx") @@ -713,7 +713,7 @@ del MyIO del obj support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) class PyIOTest(IOTest): pass @@ -1240,7 +1240,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_args_error(self): # Issue #17275 @@ -1543,7 +1543,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"123xxx") @@ -2275,7 +2275,7 @@ t = self.TextIOWrapper(b, encoding="utf-8") self.assertEqual(t.encoding, "utf-8") t = self.TextIOWrapper(b) - self.assertTrue(t.encoding is not None) + self.assertIsNotNone(t.encoding) codecs.lookup(t.encoding) def test_encoding_errors_reading(self): @@ -3062,7 +3062,7 @@ wr = weakref.ref(t) del t support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"456def") @@ -3210,7 +3210,7 @@ def test___all__(self): for name in self.io.__all__: obj = getattr(self.io, name, None) - self.assertTrue(obj is not None, name) + self.assertIsNotNone(obj, name) if name == "open": continue elif "error" in name.lower() or name == "UnsupportedOperation": @@ -3302,7 +3302,7 @@ wr = weakref.ref(c) del c, b support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_abcs(self): # Test the visible base classes are ABCs. @@ -3448,7 +3448,7 @@ received += iter(rf.read, None) sent, received = b''.join(sent), b''.join(received) - self.assertTrue(sent == received) + self.assertEqual(sent, received) self.assertTrue(wf.closed) self.assertTrue(rf.closed) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -694,7 +694,8 @@ self.assertEqual(len(state), 3) bytearray(state[0]) # Check if state[0] supports the buffer interface. self.assertIsInstance(state[1], int) - self.assertTrue(isinstance(state[2], dict) or state[2] is None) + if state[2] is not None: + self.assertIsInstance(state[2], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) @@ -794,7 +795,8 @@ self.assertIsInstance(state[0], str) self.assertIsInstance(state[1], str) self.assertIsInstance(state[2], int) - self.assertTrue(isinstance(state[3], dict) or state[3] is None) + if state[3] is not None: + self.assertIsInstance(state[3], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 14:21:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 02 Aug 2015 12:21:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIwNTU3?= =?utf-8?q?=3A_Use_specific_asserts_in_io_tests=2E?= Message-ID: <20150802122120.53969.1289@psf.io> https://hg.python.org/cpython/rev/ace74c445a3f changeset: 97200:ace74c445a3f branch: 3.4 parent: 97197:c981d9819384 user: Serhiy Storchaka date: Sun Aug 02 15:17:49 2015 +0300 summary: Issue #20557: Use specific asserts in io tests. files: Lib/test/test_bufio.py | 2 +- Lib/test/test_file.py | 4 ++-- Lib/test/test_fileio.py | 6 +++--- Lib/test/test_io.py | 20 ++++++++++---------- Lib/test/test_memoryio.py | 6 ++++-- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_bufio.py b/Lib/test/test_bufio.py --- a/Lib/test/test_bufio.py +++ b/Lib/test/test_bufio.py @@ -34,7 +34,7 @@ line = f.readline() self.assertEqual(line, s) line = f.readline() - self.assertTrue(not line) # Must be at EOF + self.assertFalse(line) # Must be at EOF f.close() finally: support.unlink(support.TESTFN) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -83,8 +83,8 @@ def testErrors(self): f = self.f self.assertEqual(f.name, TESTFN) - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) if hasattr(f, "readinto"): self.assertRaises((OSError, TypeError), f.readinto, "") diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -113,15 +113,15 @@ def testErrors(self): f = self.f - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) #self.assertEqual(f.name, TESTFN) self.assertRaises(ValueError, f.read, 10) # Open for reading f.close() self.assertTrue(f.closed) f = _FileIO(TESTFN, 'r') self.assertRaises(TypeError, f.readinto, "") - self.assertTrue(not f.closed) + self.assertFalse(f.closed) f.close() self.assertTrue(f.closed) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -453,7 +453,7 @@ with self.open(support.TESTFN, "ab") as f: self.assertEqual(f.tell(), 3) with self.open(support.TESTFN, "a") as f: - self.assertTrue(f.tell() > 0) + self.assertGreater(f.tell(), 0) def test_destructor(self): record = [] @@ -573,7 +573,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"abcxxx") @@ -717,7 +717,7 @@ del MyIO del obj support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) class PyIOTest(IOTest): pass @@ -1164,7 +1164,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_args_error(self): # Issue #17275 @@ -1467,7 +1467,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"123xxx") @@ -2199,7 +2199,7 @@ t = self.TextIOWrapper(b, encoding="utf-8") self.assertEqual(t.encoding, "utf-8") t = self.TextIOWrapper(b) - self.assertTrue(t.encoding is not None) + self.assertIsNotNone(t.encoding) codecs.lookup(t.encoding) def test_encoding_errors_reading(self): @@ -2958,7 +2958,7 @@ wr = weakref.ref(t) del t support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"456def") @@ -3106,7 +3106,7 @@ def test___all__(self): for name in self.io.__all__: obj = getattr(self.io, name, None) - self.assertTrue(obj is not None, name) + self.assertIsNotNone(obj, name) if name == "open": continue elif "error" in name.lower() or name == "UnsupportedOperation": @@ -3196,7 +3196,7 @@ wr = weakref.ref(c) del c, b support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_abcs(self): # Test the visible base classes are ABCs. @@ -3348,7 +3348,7 @@ received += iter(rf.read, None) sent, received = b''.join(sent), b''.join(received) - self.assertTrue(sent == received) + self.assertEqual(sent, received) self.assertTrue(wf.closed) self.assertTrue(rf.closed) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -693,7 +693,8 @@ self.assertEqual(len(state), 3) bytearray(state[0]) # Check if state[0] supports the buffer interface. self.assertIsInstance(state[1], int) - self.assertTrue(isinstance(state[2], dict) or state[2] is None) + if state[2] is not None: + self.assertIsInstance(state[2], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) @@ -749,7 +750,8 @@ self.assertIsInstance(state[0], str) self.assertIsInstance(state[1], str) self.assertIsInstance(state[2], int) - self.assertTrue(isinstance(state[3], dict) or state[3] is None) + if state[3] is not None: + self.assertIsInstance(state[3], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 14:21:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 02 Aug 2015 12:21:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTU3?= =?utf-8?q?=3A_Use_specific_asserts_in_io_tests=2E?= Message-ID: <20150802122120.23408.47394@psf.io> https://hg.python.org/cpython/rev/68115dd0c7f5 changeset: 97203:68115dd0c7f5 branch: 2.7 parent: 97193:e38470b49d3c user: Serhiy Storchaka date: Sun Aug 02 15:19:04 2015 +0300 summary: Issue #20557: Use specific asserts in io tests. files: Lib/test/test_bufio.py | 2 +- Lib/test/test_file.py | 4 ++-- Lib/test/test_fileio.py | 6 +++--- Lib/test/test_io.py | 20 ++++++++++---------- Lib/test/test_memoryio.py | 6 ++++-- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_bufio.py b/Lib/test/test_bufio.py --- a/Lib/test/test_bufio.py +++ b/Lib/test/test_bufio.py @@ -34,7 +34,7 @@ line = f.readline() self.assertEqual(line, s) line = f.readline() - self.assertTrue(not line) # Must be at EOF + self.assertFalse(line) # Must be at EOF f.close() finally: support.unlink(support.TESTFN) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -88,8 +88,8 @@ def testErrors(self): f = self.f self.assertEqual(f.name, TESTFN) - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) if hasattr(f, "readinto"): self.assertRaises((IOError, TypeError), f.readinto, "") diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -112,15 +112,15 @@ def testErrors(self): f = self.f - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) #self.assertEqual(f.name, TESTFN) self.assertRaises(ValueError, f.read, 10) # Open for reading f.close() self.assertTrue(f.closed) f = _FileIO(TESTFN, 'r') self.assertRaises(TypeError, f.readinto, "") - self.assertTrue(not f.closed) + self.assertFalse(f.closed) f.close() self.assertTrue(f.closed) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -426,7 +426,7 @@ with self.open(support.TESTFN, "ab") as f: self.assertEqual(f.tell(), 3) with self.open(support.TESTFN, "a") as f: - self.assertTrue(f.tell() > 0) + self.assertGreater(f.tell(), 0) def test_destructor(self): record = [] @@ -544,7 +544,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"abcxxx") @@ -668,7 +668,7 @@ del MyIO del obj support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) class PyIOTest(IOTest): test_array_writes = unittest.skip( @@ -1062,7 +1062,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_args_error(self): # Issue #17275 @@ -1365,7 +1365,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"123xxx") @@ -2063,7 +2063,7 @@ t = self.TextIOWrapper(b, encoding="utf8") self.assertEqual(t.encoding, "utf8") t = self.TextIOWrapper(b) - self.assertTrue(t.encoding is not None) + self.assertIsNotNone(t.encoding) codecs.lookup(t.encoding) def test_encoding_errors_reading(self): @@ -2687,7 +2687,7 @@ wr = weakref.ref(t) del t support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"456def") @@ -2837,7 +2837,7 @@ def test___all__(self): for name in self.io.__all__: obj = getattr(self.io, name, None) - self.assertTrue(obj is not None, name) + self.assertIsNotNone(obj, name) if name == "open": continue elif "error" in name.lower() or name == "UnsupportedOperation": @@ -2932,7 +2932,7 @@ wr = weakref.ref(c) del c, b support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_abcs(self): # Test the visible base classes are ABCs. @@ -3025,7 +3025,7 @@ received += iter(rf.read, None) sent, received = b''.join(sent), b''.join(received) - self.assertTrue(sent == received) + self.assertEqual(sent, received) self.assertTrue(wf.closed) self.assertTrue(rf.closed) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -673,7 +673,8 @@ self.assertEqual(len(state), 3) bytearray(state[0]) # Check if state[0] supports the buffer interface. self.assertIsInstance(state[1], int) - self.assertTrue(isinstance(state[2], dict) or state[2] is None) + if state[2] is not None: + self.assertIsInstance(state[2], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) @@ -729,7 +730,8 @@ self.assertIsInstance(state[0], unicode) self.assertIsInstance(state[1], str) self.assertIsInstance(state[2], int) - self.assertTrue(isinstance(state[3], dict) or state[3] is None) + if state[3] is not None: + self.assertIsInstance(state[3], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 14:21:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 02 Aug 2015 12:21:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2320557=3A_Use_specific_asserts_in_io_tests=2E?= Message-ID: <20150802122120.94768.11892@psf.io> https://hg.python.org/cpython/rev/2453ac990e5b changeset: 97201:2453ac990e5b branch: 3.5 parent: 97198:f35bdb6dd242 parent: 97200:ace74c445a3f user: Serhiy Storchaka date: Sun Aug 02 15:18:28 2015 +0300 summary: Issue #20557: Use specific asserts in io tests. files: Lib/test/test_bufio.py | 2 +- Lib/test/test_file.py | 4 ++-- Lib/test/test_fileio.py | 6 +++--- Lib/test/test_io.py | 20 ++++++++++---------- Lib/test/test_memoryio.py | 6 ++++-- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_bufio.py b/Lib/test/test_bufio.py --- a/Lib/test/test_bufio.py +++ b/Lib/test/test_bufio.py @@ -34,7 +34,7 @@ line = f.readline() self.assertEqual(line, s) line = f.readline() - self.assertTrue(not line) # Must be at EOF + self.assertFalse(line) # Must be at EOF f.close() finally: support.unlink(support.TESTFN) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -83,8 +83,8 @@ def testErrors(self): f = self.f self.assertEqual(f.name, TESTFN) - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) if hasattr(f, "readinto"): self.assertRaises((OSError, TypeError), f.readinto, "") diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -177,15 +177,15 @@ def testErrors(self): f = self.f - self.assertTrue(not f.isatty()) - self.assertTrue(not f.closed) + self.assertFalse(f.isatty()) + self.assertFalse(f.closed) #self.assertEqual(f.name, TESTFN) self.assertRaises(ValueError, f.read, 10) # Open for reading f.close() self.assertTrue(f.closed) f = self.FileIO(TESTFN, 'r') self.assertRaises(TypeError, f.readinto, "") - self.assertTrue(not f.closed) + self.assertFalse(f.closed) f.close() self.assertTrue(f.closed) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -449,7 +449,7 @@ with self.open(support.TESTFN, "ab") as f: self.assertEqual(f.tell(), 3) with self.open(support.TESTFN, "a") as f: - self.assertTrue(f.tell() > 0) + self.assertGreater(f.tell(), 0) def test_destructor(self): record = [] @@ -569,7 +569,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"abcxxx") @@ -713,7 +713,7 @@ del MyIO del obj support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) class PyIOTest(IOTest): pass @@ -1240,7 +1240,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_args_error(self): # Issue #17275 @@ -1543,7 +1543,7 @@ wr = weakref.ref(f) del f support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"123xxx") @@ -2275,7 +2275,7 @@ t = self.TextIOWrapper(b, encoding="utf-8") self.assertEqual(t.encoding, "utf-8") t = self.TextIOWrapper(b) - self.assertTrue(t.encoding is not None) + self.assertIsNotNone(t.encoding) codecs.lookup(t.encoding) def test_encoding_errors_reading(self): @@ -3062,7 +3062,7 @@ wr = weakref.ref(t) del t support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) with self.open(support.TESTFN, "rb") as f: self.assertEqual(f.read(), b"456def") @@ -3210,7 +3210,7 @@ def test___all__(self): for name in self.io.__all__: obj = getattr(self.io, name, None) - self.assertTrue(obj is not None, name) + self.assertIsNotNone(obj, name) if name == "open": continue elif "error" in name.lower() or name == "UnsupportedOperation": @@ -3302,7 +3302,7 @@ wr = weakref.ref(c) del c, b support.gc_collect() - self.assertTrue(wr() is None, wr) + self.assertIsNone(wr(), wr) def test_abcs(self): # Test the visible base classes are ABCs. @@ -3448,7 +3448,7 @@ received += iter(rf.read, None) sent, received = b''.join(sent), b''.join(received) - self.assertTrue(sent == received) + self.assertEqual(sent, received) self.assertTrue(wf.closed) self.assertTrue(rf.closed) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -694,7 +694,8 @@ self.assertEqual(len(state), 3) bytearray(state[0]) # Check if state[0] supports the buffer interface. self.assertIsInstance(state[1], int) - self.assertTrue(isinstance(state[2], dict) or state[2] is None) + if state[2] is not None: + self.assertIsInstance(state[2], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) @@ -794,7 +795,8 @@ self.assertIsInstance(state[0], str) self.assertIsInstance(state[1], str) self.assertIsInstance(state[2], int) - self.assertTrue(isinstance(state[3], dict) or state[3] is None) + if state[3] is not None: + self.assertIsInstance(state[3], dict) memio.close() self.assertRaises(ValueError, memio.__getstate__) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 15:52:24 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 02 Aug 2015 13:52:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Remove_warning?= =?utf-8?q?_about_asyncio_being_provisional_=28it=27s_not_in_3=2E5_and_up?= =?utf-8?b?KS4=?= Message-ID: <20150802135224.29404.59861@psf.io> https://hg.python.org/cpython/rev/22242581e253 changeset: 97204:22242581e253 branch: 3.5 parent: 97201:2453ac990e5b user: Guido van Rossum date: Sun Aug 02 15:50:27 2015 +0200 summary: Remove warning about asyncio being provisional (it's not in 3.5 and up). files: Doc/library/asyncio.rst | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-) diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -4,13 +4,6 @@ .. module:: asyncio :synopsis: Asynchronous I/O, event loop, coroutines and tasks. -.. note:: - - The asyncio package has been included in the standard library on a - :term:`provisional basis `. Backwards incompatible - changes (up to and including removal of the module) may occur if deemed - necessary by the core developers. - .. versionadded:: 3.4 **Source code:** :source:`Lib/asyncio/` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 15:52:24 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 02 Aug 2015 13:52:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Remove_warning_about_asyncio_being_provisional_=28it=27s?= =?utf-8?q?_not_in_3=2E5_and_up=3B_merge?= Message-ID: <20150802135224.17725.58953@psf.io> https://hg.python.org/cpython/rev/e340fe83c510 changeset: 97205:e340fe83c510 parent: 97202:859a45ca1e86 parent: 97204:22242581e253 user: Guido van Rossum date: Sun Aug 02 15:51:46 2015 +0200 summary: Remove warning about asyncio being provisional (it's not in 3.5 and up; merge from 3.5). files: Doc/library/asyncio.rst | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-) diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -4,13 +4,6 @@ .. module:: asyncio :synopsis: Asynchronous I/O, event loop, coroutines and tasks. -.. note:: - - The asyncio package has been included in the standard library on a - :term:`provisional basis `. Backwards incompatible - changes (up to and including removal of the module) may occur if deemed - necessary by the core developers. - .. versionadded:: 3.4 **Source code:** :source:`Lib/asyncio/` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 16:25:19 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 02 Aug 2015 14:25:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogRml4?= =?utf-8?q?_code_style?= Message-ID: <20150802142519.17737.81534@psf.io> https://hg.python.org/cpython/rev/da29a94367b2 changeset: 97206:da29a94367b2 branch: 3.4 parent: 97200:ace74c445a3f user: Yury Selivanov date: Sun Aug 02 10:24:34 2015 -0400 summary: asyncio: Fix code style files: Lib/asyncio/tasks.py | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -249,9 +249,8 @@ result._blocking = False result.add_done_callback(self._wakeup) self._fut_waiter = result - if self._must_cancel: - if self._fut_waiter.cancel(): - self._must_cancel = False + if self._must_cancel and self._fut_waiter.cancel(): + self._must_cancel = False else: self._loop.call_soon( self._step, None, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 16:25:19 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 02 Aug 2015 14:25:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150802142519.29392.6911@psf.io> https://hg.python.org/cpython/rev/1f81c9ab44b1 changeset: 97207:1f81c9ab44b1 branch: 3.5 parent: 97204:22242581e253 parent: 97206:da29a94367b2 user: Yury Selivanov date: Sun Aug 02 10:24:49 2015 -0400 summary: Merge 3.4 files: Lib/asyncio/tasks.py | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -249,9 +249,8 @@ result._blocking = False result.add_done_callback(self._wakeup) self._fut_waiter = result - if self._must_cancel: - if self._fut_waiter.cancel(): - self._must_cancel = False + if self._must_cancel and self._fut_waiter.cancel(): + self._must_cancel = False else: self._loop.call_soon( self._step, None, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 16:25:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 02 Aug 2015 14:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150802142520.53971.94020@psf.io> https://hg.python.org/cpython/rev/1d44d4addc17 changeset: 97208:1d44d4addc17 parent: 97205:e340fe83c510 parent: 97207:1f81c9ab44b1 user: Yury Selivanov date: Sun Aug 02 10:25:06 2015 -0400 summary: Merge 3.5 files: Lib/asyncio/tasks.py | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -249,9 +249,8 @@ result._blocking = False result.add_done_callback(self._wakeup) self._fut_waiter = result - if self._must_cancel: - if self._fut_waiter.cancel(): - self._must_cancel = False + if self._must_cancel and self._fut_waiter.cancel(): + self._must_cancel = False else: self._loop.call_soon( self._step, None, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 21:17:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 02 Aug 2015 19:17:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28=2324217=29?= Message-ID: <20150802191746.94784.36463@psf.io> https://hg.python.org/cpython/rev/25ba5e7af08a changeset: 97210:25ba5e7af08a branch: 3.5 parent: 97207:1f81c9ab44b1 parent: 97209:1838f37a8d9e user: Benjamin Peterson date: Sun Aug 02 12:16:45 2015 -0700 summary: Merge 3.4 (#24217) files: Modules/mmapmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -24,9 +24,9 @@ #ifndef MS_WINDOWS #define UNIX -# ifdef __APPLE__ +# ifdef HAVE_FCNTL_H # include -# endif +# endif /* HAVE_FCNTL_H */ #endif #ifdef MS_WINDOWS -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 21:17:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 02 Aug 2015 19:17:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_include_fcntl?= =?utf-8?q?=2Eh_on_all_*nix_platforms_=28closes_=2324217=29?= Message-ID: <20150802191746.1369.80540@psf.io> https://hg.python.org/cpython/rev/2e635a0e0207 changeset: 97212:2e635a0e0207 branch: 2.7 parent: 97203:68115dd0c7f5 user: Benjamin Peterson date: Sun Aug 02 12:15:30 2015 -0700 summary: include fcntl.h on all *nix platforms (closes #24217) Patch by Jeffrey Armstrong. files: Modules/mmapmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -23,9 +23,9 @@ #ifndef MS_WINDOWS #define UNIX -# ifdef __APPLE__ +# ifdef HAVE_FCNTL_H # include -# endif +# endif /* HAVE_FCNTL_H */ #endif #ifdef MS_WINDOWS -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 21:17:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 02 Aug 2015 19:17:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_include_fcntl?= =?utf-8?q?=2Eh_on_all_*nix_platforms_=28closes_=2324217=29?= Message-ID: <20150802191745.5531.39261@psf.io> https://hg.python.org/cpython/rev/1838f37a8d9e changeset: 97209:1838f37a8d9e branch: 3.4 parent: 97206:da29a94367b2 user: Benjamin Peterson date: Sun Aug 02 12:15:30 2015 -0700 summary: include fcntl.h on all *nix platforms (closes #24217) Patch by Jeffrey Armstrong. files: Modules/mmapmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -24,9 +24,9 @@ #ifndef MS_WINDOWS #define UNIX -# ifdef __APPLE__ +# ifdef HAVE_FCNTL_H # include -# endif +# endif /* HAVE_FCNTL_H */ #endif #ifdef MS_WINDOWS -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 21:17:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 02 Aug 2015 19:17:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQyMTcp?= Message-ID: <20150802191746.29392.2843@psf.io> https://hg.python.org/cpython/rev/4ed9cc2203b3 changeset: 97211:4ed9cc2203b3 parent: 97208:1d44d4addc17 parent: 97210:25ba5e7af08a user: Benjamin Peterson date: Sun Aug 02 12:16:54 2015 -0700 summary: merge 3.5 (#24217) files: Modules/mmapmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -24,9 +24,9 @@ #ifndef MS_WINDOWS #define UNIX -# ifdef __APPLE__ +# ifdef HAVE_FCNTL_H # include -# endif +# endif /* HAVE_FCNTL_H */ #endif #ifdef MS_WINDOWS -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 22:39:23 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 02 Aug 2015 20:39:23 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_PEP495=2C_Local_Time_Di?= =?utf-8?q?sambiguation?= Message-ID: <20150802203923.29404.37472@psf.io> https://hg.python.org/peps/rev/d78905fd943f changeset: 5915:d78905fd943f user: Alexander Belopolsky date: Sun Aug 02 16:39:16 2015 -0400 summary: Added PEP495, Local Time Disambiguation files: pep-0495-daylightsavings.png | 1 + pep-0495.rst | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/pep-0495-daylightsavings.png b/pep-0495-daylightsavings.png new file mode 120000 --- /dev/null +++ b/pep-0495-daylightsavings.png @@ -0,0 +1,1 @@ +../abalkin/ltdf/pep-0495-daylightsavings.png \ No newline at end of file diff --git a/pep-0495.rst b/pep-0495.rst new file mode 120000 --- /dev/null +++ b/pep-0495.rst @@ -0,0 +1,1 @@ +../abalkin/ltdf/pep-0495.rst \ No newline at end of file -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 2 22:50:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 02 Aug 2015 20:50:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Revert_da29a94?= =?utf-8?q?367b2?= Message-ID: <20150802205000.53989.98735@psf.io> https://hg.python.org/cpython/rev/e2b02585bb5a changeset: 97213:e2b02585bb5a branch: 3.4 parent: 97209:1838f37a8d9e user: Yury Selivanov date: Sun Aug 02 16:49:31 2015 -0400 summary: Revert da29a94367b2 files: Lib/asyncio/tasks.py | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -249,8 +249,9 @@ result._blocking = False result.add_done_callback(self._wakeup) self._fut_waiter = result - if self._must_cancel and self._fut_waiter.cancel(): - self._must_cancel = False + if self._must_cancel: + if self._fut_waiter.cancel(): + self._must_cancel = False else: self._loop.call_soon( self._step, None, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 22:50:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 02 Aug 2015 20:50:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150802205000.29402.35498@psf.io> https://hg.python.org/cpython/rev/14daad66c702 changeset: 97214:14daad66c702 branch: 3.5 parent: 97210:25ba5e7af08a parent: 97213:e2b02585bb5a user: Yury Selivanov date: Sun Aug 02 16:49:44 2015 -0400 summary: Merge 3.4 files: Lib/asyncio/tasks.py | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -249,8 +249,9 @@ result._blocking = False result.add_done_callback(self._wakeup) self._fut_waiter = result - if self._must_cancel and self._fut_waiter.cancel(): - self._must_cancel = False + if self._must_cancel: + if self._fut_waiter.cancel(): + self._must_cancel = False else: self._loop.call_soon( self._step, None, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 22:50:01 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 02 Aug 2015 20:50:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150802205001.94772.823@psf.io> https://hg.python.org/cpython/rev/f6015c08b44a changeset: 97215:f6015c08b44a parent: 97211:4ed9cc2203b3 parent: 97214:14daad66c702 user: Yury Selivanov date: Sun Aug 02 16:49:56 2015 -0400 summary: Merge 3.5 files: Lib/asyncio/tasks.py | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -249,8 +249,9 @@ result._blocking = False result.add_done_callback(self._wakeup) self._fut_waiter = result - if self._must_cancel and self._fut_waiter.cancel(): - self._must_cancel = False + if self._must_cancel: + if self._fut_waiter.cancel(): + self._must_cancel = False else: self._loop.call_soon( self._step, None, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 2 22:58:34 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 02 Aug 2015 20:58:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_PEP495=2C_Local_Time_Di?= =?utf-8?q?sambiguation?= Message-ID: <20150802205834.53993.73941@psf.io> https://hg.python.org/peps/rev/417dcbb21e13 changeset: 5916:417dcbb21e13 user: Alexander Belopolsky date: Sun Aug 02 16:58:27 2015 -0400 summary: Added PEP495, Local Time Disambiguation files: pep-0495-daylightsavings.png | Bin pep-0495.rst | 206 ++++++++++++++++++++++- 2 files changed, 205 insertions(+), 1 deletions(-) diff --git a/pep-0495-daylightsavings.png b/pep-0495-daylightsavings.png old mode 120000 new mode 100644 index e3dcd62b33571436b4e0fd5197d9ba7c6868df0d..18a1f6c2b2668295867801513a26dd3cfd8c7577 GIT binary patch [stripped] diff --git a/pep-0495.rst b/pep-0495.rst old mode 120000 new mode 100644 --- a/pep-0495.rst +++ b/pep-0495.rst @@ -1,1 +1,205 @@ -../abalkin/ltdf/pep-0495.rst \ No newline at end of file +PEP: 495 +Title: Local Time Disambiguation +Version: $Revision$ +Last-Modified: $Date$ +Author: Alexander Belopolsky +Discussions-To: Datetime-SIG +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 02-Aug-2015 + + +*********************************************************************** + Local Time Disambiguation +*********************************************************************** + +.. image:: pep-0495-daylightsavings.png + :align: center + +Abstract +======== + +This PEP adds a boolean member to the instances of ``datetime.time`` +and ``datetime.datetime`` classes that can be used to differentiate +between two moments in time for which local times are the same. + +Rationale +========= + +In the most world locations there have been and will be times when +local clocks are moved back. In those times intervals are introduced +in which local clocks show the same time twice in the same day. In +these situations, the information displayed on a local clock (or +stored in a Python datetime instance) is insufficient to identify a +particular moment in time. The proposed solution is to add a boolean +flag to the ``datetime`` instances that will distinguish between the +two ambiguous times. + +Proposal +======== + +The "first" flag +---------------- + +We propose adding a boolean member called ``first`` to the instances +of ``datetime.time`` and ``datetime.datetime`` classes. This member +should have the value True for all instances except those that +represent the second (chronologically) moment in time in an ambiguous +case. + +Affected APIs +------------- + +Attributes +.......... + +Instances of ``datetime.time`` and ``datetime.datetime`` will get a +new boolean attribute called "first." + +Constructors +............ + +The ``__new__`` methods of the ``datetime.time`` and +``datetime.datetime`` classes will get a new keyword-only argument +called ``first`` with the default value ``True``. The value of the +``first`` argument will be used to initialize the value of the +``first`` attribute in the returned instance. + +Methods +....... + +The ``replace()`` methods of the ``datetime.time`` and +``datetime.datetime`` classes will get a new keyword-only argument +called ``first`` with the default value ``True``. The value of the +``first`` argument will be used to set the value of the ``first`` +attribute in the returned instance. + +Affected Behaviors +------------------ + +The ``timestamp()`` method of ``datetime.datetime`` will return value +advanced by 3600 if ``self`` represents an ambiguous hour and +``first`` is False. + +The ``fromtimestamp()`` static method of ``datetime.datetime`` will +set the ``first`` attribute appropriately in the returned object. + + +Implementations of tzinfo +......................... + +Subclasses of ``datetime.tzinfo`` will read the values of ``first`` in +``utcoffset()`` and ``dst()`` methods and set it appropriately in the +instances returned by the ``fromutc()`` method. No change to the +signatures of these methods is proposed. + +Pickle size +----------- + +Pickle sizes for the ``datetime.datetime`` and ``datetime.time`` +objects will not change. The ``first`` flag will be encoded in the +first bit of the 5th byte of the ``datetime.datetime`` pickle payload +or the 2nd byte of the datetime.time. In the `current implementation`_ +these bytes are used to store minute value (0-59) and the first bit is +always 0. Note that ``first=True`` will be encoded as 0 in the first +bit and ``first=False`` as 1. (This change only affects pickle +format. In C implementation, the "first" member will get a full byte +to store the actual boolean value.) + +We chose the minute byte to store the the "first" bit because this +choice preserves the natural ordering. + +.. _current implementation: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17 + +Temporal Arithmetics +-------------------- + +The value of "first" will be ignored in all operations except those +that involve conversion between timezones. + +The result of addition (subtraction) of a timedelta to (from) a +datetime will always have ``first`` set to ``True`` even if the +original datetime instance had ``first=False``. + +(The only methods that will be able to produce non-default value of +"first" are ``__new__``, and ``replace()`` methods of the +``datetime.datetime`` and ``datetime.time`` classes ``now()`` and +``fromtimestamp()`` methods of the ``datetime.datetime`` class, and +``fromutc()`` method of some tzinfo implementations.) + +Comparison +---------- + +Instances of ``datetime.time`` and ``datetime.datetime`` classes that +differ only by the value of their ``first`` attribute will compare as +equal. + + +Backward and Forward Compatibility +---------------------------------- + +This proposal will have no effect on the programs that do not set the +``first`` flag explicitly or use tzinfo implementations that do. +Pickles produced by older programs will remain fully forward +compatible. Only datetime/time instances with ``first=False`` pickled +in the new versions will become unreadable by the older Python +versions. Pickles of instances with ``first=True`` (which is the +default) will remain unchanged. + +Questions and Answers +===================== + +1. Why not call the new flag "isdst"? + +------- + +* Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow! +* Bob: Should I presume initially that summer time (for example, Daylight Saving Time) is or is not (respectively) in effect for the specified time? +* Alice: Huh? + +------- + +* Bob: Alice - let's have a stargazing party at 01:30 AM tomorrow! +* Alice: You know, Bob, 01:30 AM will happen twice tomorrow. Which time do you have in mind? +* Bob: I did not think about it, but let's pick the first. + + +2. Why "first"? + + * Rejections + + * Because "second" is already there. + + * Because "later" is confusable with "latter". + + * Because "earlier" has the same issue as "first" (requires default to be True) but is two characters longer. + + * Remaining possibilities: + + * "repeated" + + * "is_first" + + * "ltdf" (Local Time Disambiguation Flag) - short and no-one will attempt to guess what it means without reading the docs. + +Implementation +============== + + * Github fork: https://github.com/abalkin/cpython + * Tracker issue: http://bugs.python.org/issue24773 + + +Copyright +========= + +This document has been placed in the public domain. + + +Picture Credit +============== + +This image is a work of a U.S. military or Department of Defense +employee, taken or made as part of that person's official duties. As a +work of the U.S. federal government, the image is in the public +domain. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 3 00:39:27 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 02 Aug 2015 22:39:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMzk3?= =?utf-8?q?=3A_Skip_failing_tests_on_AIX?= Message-ID: <20150802223927.5527.99427@psf.io> https://hg.python.org/cpython/rev/e48826904e63 changeset: 97216:e48826904e63 branch: 3.4 parent: 97213:e2b02585bb5a user: Robert Collins date: Mon Aug 03 10:36:04 2015 +1200 summary: Issue #22397: Skip failing tests on AIX Patch from David Edelsohn. files: Lib/test/test_socket.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2741,6 +2741,7 @@ self.createAndSendFDs(1) @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparate(self): # Pass two FDs in two separate arrays. Arrays may be combined @@ -2751,6 +2752,7 @@ @testFDPassSeparate.client_skip @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") def _testFDPassSeparate(self): fd0, fd1 = self.newFDs(2) self.assertEqual( @@ -2763,6 +2765,7 @@ len(MSG)) @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparateMinSpace(self): # Pass two FDs in two separate arrays, receiving them into the @@ -2775,6 +2778,7 @@ @testFDPassSeparateMinSpace.client_skip @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") def _testFDPassSeparateMinSpace(self): fd0, fd1 = self.newFDs(2) self.assertEqual( -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 3 00:39:27 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 02 Aug 2015 22:39:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2322397=3A_Skip_failing_tests_on_AIX?= Message-ID: <20150802223927.17733.8885@psf.io> https://hg.python.org/cpython/rev/a12d29f87e4c changeset: 97217:a12d29f87e4c branch: 3.5 parent: 97214:14daad66c702 parent: 97216:e48826904e63 user: Robert Collins date: Mon Aug 03 10:38:39 2015 +1200 summary: Issue #22397: Skip failing tests on AIX Patch from David Edelsohn. files: Lib/test/test_socket.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2750,6 +2750,7 @@ self.createAndSendFDs(1) @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparate(self): # Pass two FDs in two separate arrays. Arrays may be combined @@ -2760,6 +2761,7 @@ @testFDPassSeparate.client_skip @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") def _testFDPassSeparate(self): fd0, fd1 = self.newFDs(2) self.assertEqual( @@ -2772,6 +2774,7 @@ len(MSG)) @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparateMinSpace(self): # Pass two FDs in two separate arrays, receiving them into the @@ -2784,6 +2787,7 @@ @testFDPassSeparateMinSpace.client_skip @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") def _testFDPassSeparateMinSpace(self): fd0, fd1 = self.newFDs(2) self.assertEqual( -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 3 00:39:32 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 02 Aug 2015 22:39:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322397=3A_Skip_failing_tests_on_AIX?= Message-ID: <20150802223932.5537.31408@psf.io> https://hg.python.org/cpython/rev/62235755609f changeset: 97218:62235755609f parent: 97215:f6015c08b44a parent: 97217:a12d29f87e4c user: Robert Collins date: Mon Aug 03 10:39:09 2015 +1200 summary: Issue #22397: Skip failing tests on AIX Patch from David Edelsohn. files: Lib/test/test_socket.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2750,6 +2750,7 @@ self.createAndSendFDs(1) @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparate(self): # Pass two FDs in two separate arrays. Arrays may be combined @@ -2760,6 +2761,7 @@ @testFDPassSeparate.client_skip @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") def _testFDPassSeparate(self): fd0, fd1 = self.newFDs(2) self.assertEqual( @@ -2772,6 +2774,7 @@ len(MSG)) @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparateMinSpace(self): # Pass two FDs in two separate arrays, receiving them into the @@ -2784,6 +2787,7 @@ @testFDPassSeparateMinSpace.client_skip @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(sys.platform.startswith("aix"), "skipping, see issue #22397") def _testFDPassSeparateMinSpace(self): fd0, fd1 = self.newFDs(2) self.assertEqual( -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 3 05:44:26 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 03 Aug 2015 03:44:26 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Rename_extension_n?= =?utf-8?q?ame_to_=2Etxt?= Message-ID: <20150803034426.5525.37659@psf.io> https://hg.python.org/peps/rev/530a4b403713 changeset: 5917:530a4b403713 user: Berker Peksag date: Mon Aug 03 06:44:22 2015 +0300 summary: PEP 495: Rename extension name to .txt Also I made some markup changes. files: pep-0495.rst | 15 ++++++--------- 1 files changed, 6 insertions(+), 9 deletions(-) diff --git a/pep-0495.rst b/pep-0495.txt rename from pep-0495.rst rename to pep-0495.txt --- a/pep-0495.rst +++ b/pep-0495.txt @@ -10,10 +10,6 @@ Created: 02-Aug-2015 -*********************************************************************** - Local Time Disambiguation -*********************************************************************** - .. image:: pep-0495-daylightsavings.png :align: center @@ -155,7 +151,8 @@ ------- * Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow! -* Bob: Should I presume initially that summer time (for example, Daylight Saving Time) is or is not (respectively) in effect for the specified time? +* Bob: Should I presume initially that summer time (for example, Daylight + Saving Time) is or is not (respectively) in effect for the specified time? * Alice: Huh? ------- @@ -167,7 +164,7 @@ 2. Why "first"? - * Rejections +* Rejections * Because "second" is already there. @@ -175,7 +172,7 @@ * Because "earlier" has the same issue as "first" (requires default to be True) but is two characters longer. - * Remaining possibilities: +* Remaining possibilities: * "repeated" @@ -186,8 +183,8 @@ Implementation ============== - * Github fork: https://github.com/abalkin/cpython - * Tracker issue: http://bugs.python.org/issue24773 +* Github fork: https://github.com/abalkin/cpython +* Tracker issue: http://bugs.python.org/issue24773 Copyright -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 3 06:01:11 2015 From: python-checkins at python.org (nick.coghlan) Date: Mon, 03 Aug 2015 04:01:11 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_496=3A_First_draft_of_env?= =?utf-8?q?ironment_markers_PEP?= Message-ID: <20150803040111.1399.74034@psf.io> https://hg.python.org/peps/rev/99ec5a4ff1f1 changeset: 5918:99ec5a4ff1f1 user: Nick Coghlan date: Mon Aug 03 14:00:49 2015 +1000 summary: PEP 496: First draft of environment markers PEP files: pep-0426.txt | 7 + pep-0496.txt | 170 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 0 deletions(-) diff --git a/pep-0426.txt b/pep-0426.txt --- a/pep-0426.txt +++ b/pep-0426.txt @@ -64,6 +64,7 @@ * this PEP, covering the core metadata format * PEP 440, covering the versioning identification and selection scheme * PEP 459, covering several standard extensions + * PEP 496, covering environment markers * a yet-to-be-written PEP to define v2.0 of the sdist format * an updated wheel PEP (v1.1) to add pydist.json (and possibly convert the wheel metadata file from Key:Value to JSON) @@ -1353,6 +1354,12 @@ Environment markers =================== +.. note:: + + The definition of environment markers is in the process of being moved out + to a dedicated specification: PEP 496. + + An **environment marker** describes a condition about the current execution environment. They are used to indicate when certain dependencies are only required in particular environments, and to indicate supported platforms diff --git a/pep-0496.txt b/pep-0496.txt new file mode 100644 --- /dev/null +++ b/pep-0496.txt @@ -0,0 +1,170 @@ +PEP: 0496 +Title: Environment Markers +Version: $Revision$ +Last-Modified: $Date$ +Author: James Polley +BDFL-Delegate: Nick Coghlan +Status: Draft +Type: Informational +Content-Type: text/x-rst +Created: 03-Jul-2015 +Post-History: 03-Jul-2015 + + +Abstract +======== + +An **environment marker** describes a condition about the current execution +environment. They are used to indicate when certain dependencies are only +required in particular environments, and to indicate supported platforms +for distributions with additional constraints beyond the availability of a +Python runtime. + +Environment markers were first specified in PEP-0345[1]. PEP-0426[2] (which +would replace PEP-0345) proposed extensions to the markers. When +2.7.10 was released, even these extensions became insufficient due to +their reliance on simple lexical comparisons, and thus this PEP has +been born. + + +Rationale +========= + +Many Python packages are written with portability in mind. + +For many packages this means they aim to support a wide range of +Python releases. If they depend on libraries such as ``argparse`` - +which started as external libraries, but later got incorporated into +core - specifying a single set of requirements is difficult, as the +set of required packages differs depending on the version of Python in +use. + +For other packages, designing for portability means supporting +multiple operating systems. However, the significant differences +between them may mean that particular dependencies are only needed on +particular platforms (relying on ``pywin32`` only on Windows, for +example)" + +Environment Markers attempt to provide more flexibility in a list of +requirements by allowing the developer to list requirements that are +specific to a particular environment. + +Examples +======== + +Here are some examples of such markers inside a requirements.txt:: + + pywin32 >=1.0 ; sys_platform == 'win32' + unittest2 >=2.0,<3.0 ; python_version == '2.4' or python_version == '2.5' + backports.ssl_match_hostname >= 3.4 ; python_version < '2.7.9' or (python_version >= '3.0' and python_version < '3.4') + +And here's an example of some conditional metadata included in +setup.py for a distribution that requires PyWin32 both at runtime and +buildtime when using Windows:: + + setup( + install_requires=["pywin32 > 1.0 : sys.platform == 'win32'"], + setup_requires=["pywin32 > 1.0 : sys.platform == 'win32'"] + ) + + +Micro-language +============== + +The micro-language behind this is as follows. It compares: + +* strings with the ``==`` and ``in`` operators (and their opposites) +* version numbers with the ``<``, ``<=``, ``>=``, and ``<`` operators + in addition to those supported for strings + +The usual boolean operators ``and`` and ``or`` can be used to combine +expressions, and parentheses are supported for grouping. + +The pseudo-grammar is :: + + MARKER: EXPR [(and|or) EXPR]* + EXPR: ("(" MARKER ")") | (STREXPR|VEREXPR) + STREXPR: STRING [STRCMPOP STREXPR] + STRCMPOP: ==|!=|in|not in + VEREXPR: VERSION [VERCMPOP VEREXPR] + VERCMPOP: (==|!=|<|>|<=|>=) + + +``SUBEXPR`` is either a Python string (such as ``'win32'``) or one of +the ``Strings`` marker variables listed below. + +``VEREXPR`` is a PEP-0440[3] version identifier, or one of the +``Version number`` marker variables listed below. Comparisons between +version numbers are done using PEP-0440 semantics. + + +Strings +------- + +* ``os_name``: ``os.name`` +* ``sys_platform``: ``sys.platform`` +* ``platform_release``: ``platform.release()`` +* ``implementation_name``: ``sys.implementation.name`` +* ``platform_machine``: ``platform.machine()`` +* ``platform_python_implementation``: ``platform.python_implementation()`` + + +If a particular string value is not available (such as ``sys.implementation.name`` +in versions of Python prior to 3.3), the corresponding marker +variable MUST be considered equivalent to the empty string. + +If a particular version number value is not available (such as +``sys.implementation.version`` in versions of Python prior to 3.3) the +corresponding marker variable MUST be considered equivalent to ``0`` + + +Version numbers +--------------- + +* ``python_version``: ``platform.python_version()[:3]`` +* ``python_full_version``: see definition below +* ``platform_version``: ``platform.version()`` +* ``implementation_version````: see definition below + +The ``python_full_version`` and ``implementation_version`` marker variables +are derived from ``sys.version_info`` and ``sys.implementation.version`` +respectively, in accordance with the following algorithm:: + + def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + python_full_version = format_full_version(sys.version_info) + implementation_version = format_full_version(sys.implementation.version) + +``python_full_version`` will typically correspond to ``sys.version.split()[0]``. + + +References +========== + +.. [1] PEP 345, Metadata for Python Software Packages 1.2, Jones + (http://www.python.org/dev/peps/pep-0345) + +.. [2] PEP 0426, Metadata for Python Software Packages 2.0, Coghlan, Holth, Stufft + (http://www.python.org/dev/peps/pep-0426) + +.. [3] PEP 0440, Version Identification and Dependency Specification, Coghlan, Stufft + (https://www.python.org/dev/peps/pep-0440/) + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 3 06:12:53 2015 From: python-checkins at python.org (nick.coghlan) Date: Mon, 03 Aug 2015 04:12:53 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_496=3A_Working_draft_hasn?= =?utf-8?q?=27t_been_posted_yet?= Message-ID: <20150803041253.111014.33229@psf.io> https://hg.python.org/peps/rev/3f036f8c6df1 changeset: 5919:3f036f8c6df1 user: Nick Coghlan date: Mon Aug 03 14:12:45 2015 +1000 summary: PEP 496: Working draft hasn't been posted yet files: pep-0496.txt | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/pep-0496.txt b/pep-0496.txt --- a/pep-0496.txt +++ b/pep-0496.txt @@ -8,7 +8,6 @@ Type: Informational Content-Type: text/x-rst Created: 03-Jul-2015 -Post-History: 03-Jul-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 3 07:11:57 2015 From: python-checkins at python.org (brett.cannon) Date: Mon, 03 Aug 2015 05:11:57 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Explain_that_one_must_fir?= =?utf-8?q?st_join_the_hgaccounts_account_before_one_can?= Message-ID: <20150803051157.5537.99697@psf.io> https://hg.python.org/devguide/rev/68b06ae9aee4 changeset: 757:68b06ae9aee4 user: Brett Cannon date: Sun Aug 02 22:10:57 2015 -0700 summary: Explain that one must first join the hgaccounts account before one can check out the SSH keys to manage. files: developers.rst | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -464,7 +464,13 @@ Procedure for Granting or Dropping Access ----------------------------------------- -Obtain a checkout of the keys repo:: +To be granted the ability to manage SSH keys for committers, you must first +submit a pull request to the `psf-salt repo +`_ +to add your own SSH key to the hgaccounts account. + +Once you have been added to the hgaccounts accout, obtain a checkout of the keys +repo:: hg clone ssh://hgaccounts at hg.python.org/repo @@ -473,5 +479,3 @@ automatically regenerate the ``authorized_keys`` file for the ``hg`` user. Make sure to update the developer log above. -To add or remove hg account admins, submit pull requests to the `psf-salt repo -`_. -- Repository URL: https://hg.python.org/devguide From lp_benchmark_robot at intel.com Mon Aug 3 09:50:43 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Mon, 3 Aug 2015 07:50:43 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-03 Message-ID: Results for project python_default-nightly, build date 2015-08-03 10:41:26 commit: 62235755609f0e2e94acb5e724bc1026d6530651 revision date: 2015-08-03 01:39:09 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec -1.07439% -3.86021% :-( regex_v8 sec -0.79618% -4.52187% :-| nbody sec 0.26330% -0.66895% :-| json_dump_v2 sec 0.24798% -1.93585% :-| normal_startup sec 0.07573% -0.26223% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From solipsis at pitrou.net Mon Aug 3 10:45:00 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 03 Aug 2015 08:45:00 +0000 Subject: [Python-checkins] Daily reference leaks (62235755609f): sum=-1 Message-ID: <20150803084500.29390.96605@psf.io> results for 62235755609f on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_collections leaked [-6, 0, 0] references, sum=-6 test_collections leaked [-3, 1, 0] memory blocks, sum=-2 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogONBFOH', '--timeout', '7200'] From python-checkins at python.org Mon Aug 3 18:55:25 2015 From: python-checkins at python.org (jesus.cea) Date: Mon, 03 Aug 2015 16:55:25 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Copyright?= Message-ID: <20150803165525.23394.15039@psf.io> https://hg.python.org/devguide/rev/681e28b06256 changeset: 758:681e28b06256 user: Jesus Cea date: Mon Aug 03 18:55:17 2015 +0200 summary: Copyright files: conf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/conf.py b/conf.py --- a/conf.py +++ b/conf.py @@ -43,7 +43,7 @@ # General information about the project. project = u'Python Developer\'s Guide' -copyright = u'2011-2014, Python Software Foundation' +copyright = u'2011-2015, Python Software Foundation' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Mon Aug 3 20:57:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 03 Aug 2015 18:57:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_whatsnew/3=2E5=2C3=2E6=3A_Mention_that_=27async=27_is_a_?= =?utf-8?q?bad_name_for_modules?= Message-ID: <20150803185733.94784.84308@psf.io> https://hg.python.org/cpython/rev/5a13a3f3bb3b changeset: 97220:5a13a3f3bb3b parent: 97218:62235755609f parent: 97219:0f2fc3e7816d user: Yury Selivanov date: Mon Aug 03 14:57:21 2015 -0400 summary: whatsnew/3.5,3.6: Mention that 'async' is a bad name for modules files: Doc/whatsnew/3.5.rst | 6 +++--- Doc/whatsnew/3.6.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -947,9 +947,9 @@ New Keywords ------------ -``async`` and ``await`` are not recommended to be used as variable, class or -function names. Introduced by :pep:`492` in Python 3.5, they will become -proper keywords in Python 3.7. +``async`` and ``await`` are not recommended to be used as variable, class, +function or module names. Introduced by :pep:`492` in Python 3.5, they will +become proper keywords in Python 3.7. Unsupported Operating Systems diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -116,9 +116,9 @@ New Keywords ------------ -``async`` and ``await`` are not recommended to be used as variable, class or -function names. Introduced by :pep:`492` in Python 3.5, they will become -proper keywords in Python 3.7. +``async`` and ``await`` are not recommended to be used as variable, class, +function or module names. Introduced by :pep:`492` in Python 3.5, they will +become proper keywords in Python 3.7. Deprecated Python modules, functions and methods -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 3 20:57:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 03 Aug 2015 18:57:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogd2hhdHNuZXcvMy41?= =?utf-8?q?=3A_Mention_that_=27async=27_is_a_bad_name_for_modules?= Message-ID: <20150803185732.29402.98193@psf.io> https://hg.python.org/cpython/rev/0f2fc3e7816d changeset: 97219:0f2fc3e7816d branch: 3.5 parent: 97217:a12d29f87e4c user: Yury Selivanov date: Mon Aug 03 14:55:58 2015 -0400 summary: whatsnew/3.5: Mention that 'async' is a bad name for modules files: Doc/whatsnew/3.5.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -947,9 +947,9 @@ New Keywords ------------ -``async`` and ``await`` are not recommended to be used as variable, class or -function names. Introduced by :pep:`492` in Python 3.5, they will become -proper keywords in Python 3.7. +``async`` and ``await`` are not recommended to be used as variable, class, +function or module names. Introduced by :pep:`492` in Python 3.5, they will +become proper keywords in Python 3.7. Unsupported Operating Systems -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:07:55 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 03 Aug 2015 22:07:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODg4?= =?utf-8?q?=3A_Handle_fractional_time_in_cookie_expiry=2E_Patch_by_ssh=2E?= Message-ID: <20150803220755.17709.29551@psf.io> https://hg.python.org/cpython/rev/1c1c508d1b98 changeset: 97221:1c1c508d1b98 branch: 3.4 parent: 97216:e48826904e63 user: Robert Collins date: Tue Aug 04 10:06:29 2015 +1200 summary: Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. files: Lib/http/cookiejar.py | 2 +- Lib/test/test_http_cookiejar.py | 9 +++++++++ Misc/NEWS | 2 ++ 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -758,7 +758,7 @@ ): if version is not None: version = int(version) - if expires is not None: expires = int(expires) + if expires is not None: expires = int(float(expires)) if port is None and port_specified is True: raise ValueError("if port is None, port_specified must be false") diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -566,6 +566,15 @@ self.assertEqual(len(c), 1) self.assertIn('spam="bar"', h) + # test if fractional expiry is accepted + cookie = Cookie(0, "name", "value", + None, False, "www.python.org", + True, False, "/", + False, False, "1444312383.018307", + False, None, None, + {}) + self.assertEqual(cookie.expires, 1444312383) + # XXX RFC 2965 expiry rules (some apply to V0 too) def test_default_path(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Library ------- +- Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Patch by Matt Frank. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:07:55 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 03 Aug 2015 22:07:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323888=3A_Handle_fractional_time_in_cookie_expiry=2E_P?= =?utf-8?q?atch_by_ssh=2E?= Message-ID: <20150803220755.5539.39618@psf.io> https://hg.python.org/cpython/rev/06406205ae99 changeset: 97222:06406205ae99 branch: 3.5 parent: 97219:0f2fc3e7816d parent: 97221:1c1c508d1b98 user: Robert Collins date: Tue Aug 04 10:07:06 2015 +1200 summary: Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. files: Lib/http/cookiejar.py | 2 +- Lib/test/test_http_cookiejar.py | 9 +++++++++ Misc/NEWS | 2 ++ 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -758,7 +758,7 @@ ): if version is not None: version = int(version) - if expires is not None: expires = int(expires) + if expires is not None: expires = int(float(expires)) if port is None and port_specified is True: raise ValueError("if port is None, port_specified must be false") diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -566,6 +566,15 @@ self.assertEqual(len(c), 1) self.assertIn('spam="bar"', h) + # test if fractional expiry is accepted + cookie = Cookie(0, "name", "value", + None, False, "www.python.org", + True, False, "/", + False, False, "1444312383.018307", + False, None, None, + {}) + self.assertEqual(cookie.expires, 1444312383) + # XXX RFC 2965 expiry rules (some apply to V0 too) def test_default_path(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Patch by Matt Frank. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:07:55 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 03 Aug 2015 22:07:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323888=3A_Handle_fractional_time_in_cookie_expir?= =?utf-8?q?y=2E_Patch_by_ssh=2E?= Message-ID: <20150803220755.5527.19327@psf.io> https://hg.python.org/cpython/rev/73902903d397 changeset: 97223:73902903d397 parent: 97220:5a13a3f3bb3b parent: 97222:06406205ae99 user: Robert Collins date: Tue Aug 04 10:07:21 2015 +1200 summary: Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. files: Lib/http/cookiejar.py | 2 +- Lib/test/test_http_cookiejar.py | 9 +++++++++ Misc/NEWS | 2 ++ 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -758,7 +758,7 @@ ): if version is not None: version = int(version) - if expires is not None: expires = int(expires) + if expires is not None: expires = int(float(expires)) if port is None and port_specified is True: raise ValueError("if port is None, port_specified must be false") diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -566,6 +566,15 @@ self.assertEqual(len(c), 1) self.assertIn('spam="bar"', h) + # test if fractional expiry is accepted + cookie = Cookie(0, "name", "value", + None, False, "www.python.org", + True, False, "/", + False, False, "1444312383.018307", + False, None, None, + {}) + self.assertEqual(cookie.expires, 1444312383) + # XXX RFC 2965 expiry rules (some apply to V0 too) def test_default_path(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Patch by Matt Frank. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:34 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzU5?= =?utf-8?q?=3A_Revert_13a8782a775e=2E?= Message-ID: <20150803224534.53991.3303@psf.io> https://hg.python.org/cpython/rev/06852194f541 changeset: 97225:06852194f541 branch: 3.4 parent: 97216:e48826904e63 user: Terry Jan Reedy date: Mon Aug 03 18:34:22 2015 -0400 summary: Issue #24759: Revert 13a8782a775e. files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox -try: - from tkinter import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:34 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324759=3A_Merge_with_3=2E4?= Message-ID: <20150803224534.17731.29728@psf.io> https://hg.python.org/cpython/rev/863e3cdbbabe changeset: 97226:863e3cdbbabe branch: 3.5 parent: 97219:0f2fc3e7816d parent: 97225:06852194f541 user: Terry Jan Reedy date: Mon Aug 03 18:34:45 2015 -0400 summary: Issue #24759: Merge with 3.4 files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox -try: - from tkinter import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:34 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324759=3A_Merge_with_3=2E5?= Message-ID: <20150803224534.17721.19923@psf.io> https://hg.python.org/cpython/rev/3bcb184b62f8 changeset: 97227:3bcb184b62f8 parent: 97220:5a13a3f3bb3b parent: 97226:863e3cdbbabe user: Terry Jan Reedy date: Mon Aug 03 18:35:09 2015 -0400 summary: Issue #24759: Merge with 3.5 files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox -try: - from tkinter import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:34 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NzU5?= =?utf-8?q?=3A_Revert_8203fc75b3d2=2E?= Message-ID: <20150803224534.5541.43970@psf.io> https://hg.python.org/cpython/rev/0511b1165bb6 changeset: 97224:0511b1165bb6 branch: 2.7 parent: 97212:2e635a0e0207 user: Terry Jan Reedy date: Mon Aug 03 18:34:07 2015 -0400 summary: Issue #24759: Revert 8203fc75b3d2. files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkMessageBox -try: - import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the Tkinter ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:36 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge?= Message-ID: <20150803224534.94780.93977@psf.io> https://hg.python.org/cpython/rev/94eed63ffe75 changeset: 97229:94eed63ffe75 branch: 3.5 parent: 97222:06406205ae99 parent: 97226:863e3cdbbabe user: Terry Jan Reedy date: Mon Aug 03 18:41:57 2015 -0400 summary: Merge files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox -try: - from tkinter import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:36 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_Merge?= Message-ID: <20150803224534.110904.65258@psf.io> https://hg.python.org/cpython/rev/984b96ea0ba7 changeset: 97228:984b96ea0ba7 branch: 3.4 parent: 97221:1c1c508d1b98 parent: 97225:06852194f541 user: Terry Jan Reedy date: Mon Aug 03 18:41:16 2015 -0400 summary: Merge files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox -try: - from tkinter import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:40 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <20150803224540.29386.98378@psf.io> https://hg.python.org/cpython/rev/116b25660717 changeset: 97230:116b25660717 parent: 97223:73902903d397 parent: 97227:3bcb184b62f8 user: Terry Jan Reedy date: Mon Aug 03 18:42:40 2015 -0400 summary: Merge files: Lib/idlelib/PyShell.py | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -23,16 +23,6 @@ "Your Python may not be configured for Tk. **", file=sys.__stderr__) sys.exit(1) import tkinter.messagebox as tkMessageBox -try: - from tkinter import ttk -except: - root = Tk() - root.withdraw() - tkMessageBox.showerror("Idle Cannot Start", - "Idle now requires the tkinter.ttk module from tcl/tk 8.5+.\n" - + "It found tk %s and no ttk." % TkVersion, - parent=root) - sys.exit(1) from idlelib.EditorWindow import EditorWindow, fixwordbreaks from idlelib.FileList import FileList -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:40 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150803224540.5525.44159@psf.io> https://hg.python.org/cpython/rev/b09b80dfe688 changeset: 97232:b09b80dfe688 parent: 97230:116b25660717 parent: 97231:fedf802b6ec1 user: Terry Jan Reedy date: Mon Aug 03 18:44:20 2015 -0400 summary: Merge with 3.5 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 00:45:40 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 03 Aug 2015 22:45:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150803224540.41825.64044@psf.io> https://hg.python.org/cpython/rev/fedf802b6ec1 changeset: 97231:fedf802b6ec1 branch: 3.5 parent: 97229:94eed63ffe75 parent: 97228:984b96ea0ba7 user: Terry Jan Reedy date: Mon Aug 03 18:43:50 2015 -0400 summary: Merge with 3.4 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 01:22:41 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 03 Aug 2015 23:22:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Nzcx?= =?utf-8?q?=3A_Adds_vcruntime_DLL_to_tcltk_package?= Message-ID: <20150803232241.111049.42844@psf.io> https://hg.python.org/cpython/rev/e9f91d47c8ab changeset: 97233:e9f91d47c8ab branch: 3.5 parent: 97231:fedf802b6ec1 user: Steve Dower date: Mon Aug 03 16:21:12 2015 -0700 summary: Issue #24771: Adds vcruntime DLL to tcltk package files: Tools/msi/tcltk/tcltk.wixproj | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -27,6 +27,13 @@ DLLs\ tcltk_dlls + + $(VCInstallDir)redist\$(Platform)\ + $(VCInstallDir)redist\$(Platform)\ + $(VCInstallDir)redist\$(Platform)\ + DLLs\ + tcltk_dlls + $(tcltkDir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 01:22:41 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 03 Aug 2015 23:22:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324771=3A_Adds_vcruntime_DLL_to_tcltk_package?= Message-ID: <20150803232241.17709.66874@psf.io> https://hg.python.org/cpython/rev/14dee84ab900 changeset: 97234:14dee84ab900 parent: 97232:b09b80dfe688 parent: 97233:e9f91d47c8ab user: Steve Dower date: Mon Aug 03 16:21:39 2015 -0700 summary: Issue #24771: Adds vcruntime DLL to tcltk package files: Tools/msi/tcltk/tcltk.wixproj | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -27,6 +27,13 @@ DLLs\ tcltk_dlls + + $(VCInstallDir)redist\$(Platform)\ + $(VCInstallDir)redist\$(Platform)\ + $(VCInstallDir)redist\$(Platform)\ + DLLs\ + tcltk_dlls + $(tcltkDir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 02:53:39 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 00:53:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324021=3A_docstring_for_urllib=2Eurlcleanup=2E?= Message-ID: <20150804005339.94780.4143@psf.io> https://hg.python.org/cpython/rev/43ed41cdd3c2 changeset: 97237:43ed41cdd3c2 parent: 97234:14dee84ab900 parent: 97236:6fd69aeb8a3b user: Robert Collins date: Tue Aug 04 12:52:58 2015 +1200 summary: Issue #24021: docstring for urllib.urlcleanup. Patch from Daniel Andrade Groppe and Peter Lovett files: Lib/urllib/request.py | 1 + Misc/ACKS | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -230,6 +230,7 @@ return result def urlcleanup(): + """Clean up temporary files from urlretrieve calls.""" for temp_file in _url_tempfiles: try: os.unlink(temp_file) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -518,6 +518,7 @@ Olivier Grisel Fabian Groffen Eric Groo +Daniel Andrade Groppe Dag Gruneau Filip Gruszczy?ski Thomas Guettler @@ -860,6 +861,7 @@ Tom Loredo Justin Love Ned Jackson Lovely +Peter Lovett Chalmer Lowe Jason Lowe Tony Lownds -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 02:53:38 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 00:53:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324021=3A_docstring_for_urllib=2Eurlcleanup=2E?= Message-ID: <20150804005338.29410.72107@psf.io> https://hg.python.org/cpython/rev/6fd69aeb8a3b changeset: 97236:6fd69aeb8a3b branch: 3.5 parent: 97233:e9f91d47c8ab parent: 97235:659f5adc2354 user: Robert Collins date: Tue Aug 04 12:52:43 2015 +1200 summary: Issue #24021: docstring for urllib.urlcleanup. Patch from Daniel Andrade Groppe and Peter Lovett files: Lib/urllib/request.py | 1 + Misc/ACKS | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -230,6 +230,7 @@ return result def urlcleanup(): + """Clean up temporary files from urlretrieve calls.""" for temp_file in _url_tempfiles: try: os.unlink(temp_file) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -518,6 +518,7 @@ Olivier Grisel Fabian Groffen Eric Groo +Daniel Andrade Groppe Dag Gruneau Filip Gruszczy?ski Thomas Guettler @@ -860,6 +861,7 @@ Tom Loredo Justin Love Ned Jackson Lovely +Peter Lovett Chalmer Lowe Jason Lowe Tony Lownds -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 02:53:38 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 00:53:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDIx?= =?utf-8?q?=3A_docstring_for_urllib=2Eurlcleanup=2E?= Message-ID: <20150804005338.17711.32612@psf.io> https://hg.python.org/cpython/rev/659f5adc2354 changeset: 97235:659f5adc2354 branch: 3.4 parent: 97228:984b96ea0ba7 user: Robert Collins date: Tue Aug 04 12:52:06 2015 +1200 summary: Issue #24021: docstring for urllib.urlcleanup. Patch from Daniel Andrade Groppe and Peter Lovett files: Lib/urllib/request.py | 1 + Misc/ACKS | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -229,6 +229,7 @@ return result def urlcleanup(): + """Clean up temporary files from urlretrieve calls.""" for temp_file in _url_tempfiles: try: os.unlink(temp_file) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -508,6 +508,7 @@ Olivier Grisel Fabian Groffen Eric Groo +Daniel Andrade Groppe Dag Gruneau Filip Gruszczy?ski Thomas Guettler @@ -836,6 +837,7 @@ Tom Loredo Justin Love Ned Jackson Lovely +Peter Lovett Jason Lowe Tony Lownds Ray Loyzaga -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Tue Aug 4 09:31:39 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Tue, 4 Aug 2015 07:31:39 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-04 Message-ID: Results for project python_default-nightly, build date 2015-08-04 09:02:09 commit: 43ed41cdd3c26c3611f6bf7d5ccb618316477a67 revision date: 2015-08-04 03:52:58 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec 1.10696% -2.71052% :-( regex_v8 sec 1.49910% -2.95498% :-| nbody sec 0.14245% -0.52555% :-| json_dump_v2 sec 0.85780% -1.06145% :-| normal_startup sec 0.11044% -0.15150% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From solipsis at pitrou.net Tue Aug 4 10:46:36 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 04 Aug 2015 08:46:36 +0000 Subject: [Python-checkins] Daily reference leaks (43ed41cdd3c2): sum=4 Message-ID: <20150804084636.111049.82950@psf.io> results for 43ed41cdd3c2 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog7Jerpf', '--timeout', '7200'] From python-checkins at python.org Tue Aug 4 16:10:17 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Tue, 04 Aug 2015 14:10:17 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Make_image_smaller?= =?utf-8?q?_and_place_it_in_a_sidebar=2E?= Message-ID: <20150804141008.23394.46945@psf.io> https://hg.python.org/peps/rev/46b678bf07d2 changeset: 5920:46b678bf07d2 user: Alexander Belopolsky date: Tue Aug 04 10:10:01 2015 -0400 summary: PEP 495: Make image smaller and place it in a sidebar. files: pep-0495.txt | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -10,8 +10,6 @@ Created: 02-Aug-2015 -.. image:: pep-0495-daylightsavings.png - :align: center Abstract ======== @@ -20,6 +18,13 @@ and ``datetime.datetime`` classes that can be used to differentiate between two moments in time for which local times are the same. +.. sidebar:: US public service advertisement + + .. image:: pep-0495-daylightsavings.png + :align: right + :width: 15% + + Rationale ========= @@ -164,21 +169,29 @@ 2. Why "first"? -* Rejections +* Rejections: + + **second** + rejected because "second" is already there. - * Because "second" is already there. + **later** + rejected because "later" is confusable with "latter". - * Because "later" is confusable with "latter". - - * Because "earlier" has the same issue as "first" (requires default to be True) but is two characters longer. + **earlier** + rejected because "earlier" has the same issue as "first" (requires + default to be True) but is two characters longer. * Remaining possibilities: - * "repeated" + **repeated** + this is a strong candidate - * "is_first" + **is_first** + arguably more grammatically correct than "first" - * "ltdf" (Local Time Disambiguation Flag) - short and no-one will attempt to guess what it means without reading the docs. + **ltdf** + (Local Time Disambiguation Flag) - short and no-one will + attempt to guess what it means without reading the docs. Implementation ============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 4 18:42:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 16:42:51 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogd2hhdHNuZXcvMy41?= =?utf-8?q?=3A_Mention_PEP_448?= Message-ID: <20150804164251.23404.45778@psf.io> https://hg.python.org/cpython/rev/731b8caaa855 changeset: 97238:731b8caaa855 branch: 3.5 parent: 97236:6fd69aeb8a3b user: Yury Selivanov date: Tue Aug 04 12:42:20 2015 -0400 summary: whatsnew/3.5: Mention PEP 448 files: Doc/whatsnew/3.5.rst | 43 ++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -203,6 +203,49 @@ :pep:`465` -- A dedicated infix operator for matrix multiplication +PEP 448 - Additional Unpacking Generalizations +---------------------------------------------- + +This PEP proposes extended usages of the ``*`` iterable unpacking +operator and ``**`` dictionary unpacking operators +to allow unpacking in more positions, an arbitrary number of +times, and in additional circumstances. Specifically, +in function calls, in comprehensions and generator expressions, and +in displays. + +Function calls are proposed to support an arbitrary number of +unpackings rather than just one:: + + >>> print(*[1], *[2], 3) + 1 2 3 + >>> dict(**{'x': 1}, y=2, **{'z': 3}) + {'x': 1, 'y': 2, 'z': 3} + +Unpacking is proposed to be allowed inside tuple, list, set, +and dictionary displays:: + + >>> *range(4), 4 + (0, 1, 2, 3, 4) + >>> [*range(4), 4] + [0, 1, 2, 3, 4] + >>> {*range(4), 4} + {0, 1, 2, 3, 4} + >>> {'x': 1, **{'y': 2}} + {'x': 1, 'y': 2} + +In dictionaries, later values will always override earlier ones:: + + >>> {'x': 1, **{'x': 2}} + {'x': 2} + + >>> {**{'x': 2}, 'x': 1} + {'x': 1} + +.. seealso:: + + :pep:`448` -- Additional Unpacking Generalizations + + PEP 471 - os.scandir() function -- a better and faster directory iterator ------------------------------------------------------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 18:42:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 16:42:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41ICh3aGF0c25ldyk=?= Message-ID: <20150804164251.17735.45836@psf.io> https://hg.python.org/cpython/rev/0c965f6c45ef changeset: 97239:0c965f6c45ef parent: 97237:43ed41cdd3c2 parent: 97238:731b8caaa855 user: Yury Selivanov date: Tue Aug 04 12:42:36 2015 -0400 summary: Merge 3.5 (whatsnew) files: Doc/whatsnew/3.5.rst | 43 ++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -203,6 +203,49 @@ :pep:`465` -- A dedicated infix operator for matrix multiplication +PEP 448 - Additional Unpacking Generalizations +---------------------------------------------- + +This PEP proposes extended usages of the ``*`` iterable unpacking +operator and ``**`` dictionary unpacking operators +to allow unpacking in more positions, an arbitrary number of +times, and in additional circumstances. Specifically, +in function calls, in comprehensions and generator expressions, and +in displays. + +Function calls are proposed to support an arbitrary number of +unpackings rather than just one:: + + >>> print(*[1], *[2], 3) + 1 2 3 + >>> dict(**{'x': 1}, y=2, **{'z': 3}) + {'x': 1, 'y': 2, 'z': 3} + +Unpacking is proposed to be allowed inside tuple, list, set, +and dictionary displays:: + + >>> *range(4), 4 + (0, 1, 2, 3, 4) + >>> [*range(4), 4] + [0, 1, 2, 3, 4] + >>> {*range(4), 4} + {0, 1, 2, 3, 4} + >>> {'x': 1, **{'y': 2}} + {'x': 1, 'y': 2} + +In dictionaries, later values will always override earlier ones:: + + >>> {'x': 1, **{'x': 2}} + {'x': 2} + + >>> {**{'x': 2}, 'x': 1} + {'x': 1} + +.. seealso:: + + :pep:`448` -- Additional Unpacking Generalizations + + PEP 471 - os.scandir() function -- a better and faster directory iterator ------------------------------------------------------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 18:47:24 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 16:47:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogd2hhdHNuZXcvMy41?= =?utf-8?q?=3A_Briefly_mention_PEP_484?= Message-ID: <20150804164720.23406.79209@psf.io> https://hg.python.org/cpython/rev/5b143ec2b614 changeset: 97240:5b143ec2b614 branch: 3.5 parent: 97238:731b8caaa855 user: Yury Selivanov date: Tue Aug 04 12:46:57 2015 -0400 summary: whatsnew/3.5: Briefly mention PEP 484 files: Doc/whatsnew/3.5.rst | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -246,6 +246,28 @@ :pep:`448` -- Additional Unpacking Generalizations +PEP 484 - Type Hints +-------------------- + +This PEP introduces a provisional module to provide these standard +definitions and tools, along with some conventions for situations +where annotations are not available. + +For example, here is a simple function whose argument and return type +are declared in the annotations:: + + def greeting(name: str) -> str: + return 'Hello ' + name + +The type system supports unions, generic types, and a special type +named ``Any`` which is consistent with (i.e. assignable to and from) all +types. + +.. seealso:: + + :pep:`484` -- Type Hints + + PEP 471 - os.scandir() function -- a better and faster directory iterator ------------------------------------------------------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 18:47:24 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 16:47:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41ICh3aGF0c25ldyk=?= Message-ID: <20150804164721.53969.33846@psf.io> https://hg.python.org/cpython/rev/11a065d6e5f4 changeset: 97241:11a065d6e5f4 parent: 97239:0c965f6c45ef parent: 97240:5b143ec2b614 user: Yury Selivanov date: Tue Aug 04 12:47:12 2015 -0400 summary: Merge 3.5 (whatsnew) files: Doc/whatsnew/3.5.rst | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -246,6 +246,28 @@ :pep:`448` -- Additional Unpacking Generalizations +PEP 484 - Type Hints +-------------------- + +This PEP introduces a provisional module to provide these standard +definitions and tools, along with some conventions for situations +where annotations are not available. + +For example, here is a simple function whose argument and return type +are declared in the annotations:: + + def greeting(name: str) -> str: + return 'Hello ' + name + +The type system supports unions, generic types, and a special type +named ``Any`` which is consistent with (i.e. assignable to and from) all +types. + +.. seealso:: + + :pep:`484` -- Type Hints + + PEP 471 - os.scandir() function -- a better and faster directory iterator ------------------------------------------------------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 18:52:35 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 16:52:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogd2hhdHNuZXc6IEFk?= =?utf-8?q?d_pep_448_to_new_syntax_features_section?= Message-ID: <20150804165235.1369.80899@psf.io> https://hg.python.org/cpython/rev/45d1baa4fe62 changeset: 97242:45d1baa4fe62 branch: 3.5 parent: 97240:5b143ec2b614 user: Yury Selivanov date: Tue Aug 04 12:52:16 2015 -0400 summary: whatsnew: Add pep 448 to new syntax features section files: Doc/whatsnew/3.5.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -71,6 +71,7 @@ * :pep:`465`, a new matrix multiplication operator: ``a @ b``. * :pep:`492`, coroutines with async and await syntax. +* :pep:`448`, additional unpacking generalizations. New library modules: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 18:52:40 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 16:52:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41ICh3aGF0c25ldyk=?= Message-ID: <20150804165235.23404.4865@psf.io> https://hg.python.org/cpython/rev/b363cddc2c81 changeset: 97243:b363cddc2c81 parent: 97241:11a065d6e5f4 parent: 97242:45d1baa4fe62 user: Yury Selivanov date: Tue Aug 04 12:52:32 2015 -0400 summary: Merge 3.5 (whatsnew) files: Doc/whatsnew/3.5.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -71,6 +71,7 @@ * :pep:`465`, a new matrix multiplication operator: ``a @ b``. * :pep:`492`, coroutines with async and await syntax. +* :pep:`448`, additional unpacking generalizations. New library modules: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 21:38:35 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 19:38:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150804193834.41841.4596@psf.io> https://hg.python.org/cpython/rev/07c0384eaacb changeset: 97245:07c0384eaacb branch: 3.5 parent: 97242:45d1baa4fe62 parent: 97244:527f1bbf1840 user: Yury Selivanov date: Tue Aug 04 15:37:45 2015 -0400 summary: Merge 3.4 files: Lib/asyncio/base_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1205,7 +1205,7 @@ return enabled = bool(enabled) - if self._coroutine_wrapper_set is enabled: + if self._coroutine_wrapper_set == enabled: return wrapper = coroutines.debug_wrapper -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 21:38:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 19:38:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150804193834.29394.62805@psf.io> https://hg.python.org/cpython/rev/6d9d3a866b2b changeset: 97246:6d9d3a866b2b parent: 97243:b363cddc2c81 parent: 97245:07c0384eaacb user: Yury Selivanov date: Tue Aug 04 15:37:58 2015 -0400 summary: Merge 3.5 files: Lib/asyncio/base_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1205,7 +1205,7 @@ return enabled = bool(enabled) - if self._coroutine_wrapper_set is enabled: + if self._coroutine_wrapper_set == enabled: return wrapper = coroutines.debug_wrapper -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 21:38:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 19:38:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogU3lu?= =?utf-8?q?c_with_mainstream?= Message-ID: <20150804193833.17733.44984@psf.io> https://hg.python.org/cpython/rev/527f1bbf1840 changeset: 97244:527f1bbf1840 branch: 3.4 parent: 97235:659f5adc2354 user: Yury Selivanov date: Tue Aug 04 15:37:24 2015 -0400 summary: asyncio: Sync with mainstream files: Lib/asyncio/base_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1205,7 +1205,7 @@ return enabled = bool(enabled) - if self._coroutine_wrapper_set is enabled: + if self._coroutine_wrapper_set == enabled: return wrapper = coroutines.debug_wrapper -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:01:32 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 20:01:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150804200132.5529.36841@psf.io> https://hg.python.org/cpython/rev/e3f381a3423d changeset: 97248:e3f381a3423d branch: 3.5 parent: 97245:07c0384eaacb parent: 97247:99550a01fa6e user: Yury Selivanov date: Tue Aug 04 15:56:53 2015 -0400 summary: Merge 3.4 files: Lib/asyncio/base_events.py | 3 ++- Lib/asyncio/base_subprocess.py | 4 ++-- Lib/asyncio/proactor_events.py | 4 ++-- Lib/asyncio/selector_events.py | 4 ++-- Lib/asyncio/sslproto.py | 4 ++-- Lib/asyncio/unix_events.py | 5 +++-- Lib/test/test_asyncio/test_subprocess.py | 6 +----- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -28,6 +28,7 @@ import sys import warnings +from . import compat from . import coroutines from . import events from . import futures @@ -378,7 +379,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self.is_closed(): warnings.warn("unclosed event loop %r" % self, ResourceWarning) diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -1,8 +1,8 @@ import collections import subprocess -import sys import warnings +from . import compat from . import futures from . import protocols from . import transports @@ -116,7 +116,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self._closed: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -7,10 +7,10 @@ __all__ = ['BaseProactorEventLoop'] import socket -import sys import warnings from . import base_events +from . import compat from . import constants from . import futures from . import sslproto @@ -79,7 +79,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._sock is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -10,7 +10,6 @@ import errno import functools import socket -import sys import warnings try: import ssl @@ -18,6 +17,7 @@ ssl = None from . import base_events +from . import compat from . import constants from . import events from . import futures @@ -568,7 +568,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._sock is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -1,11 +1,11 @@ import collections -import sys import warnings try: import ssl except ImportError: # pragma: no cover ssl = None +from . import compat from . import protocols from . import transports from .log import logger @@ -317,7 +317,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self._closed: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -13,6 +13,7 @@ from . import base_events from . import base_subprocess +from . import compat from . import constants from . import coroutines from . import events @@ -370,7 +371,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._pipe is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) @@ -555,7 +556,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._pipe is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,11 +417,7 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - if sys.platform == 'win32': - target = 'asyncio.windows_utils.Popen' - else: - target = 'subprocess.Popen' - with mock.patch(target) as popen: + with mock.patch('subprocess.Popen') as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:01:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 20:01:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogU3lu?= =?utf-8?q?c_with_upstream_=28compat_module=29?= Message-ID: <20150804200132.110661.89228@psf.io> https://hg.python.org/cpython/rev/99550a01fa6e changeset: 97247:99550a01fa6e branch: 3.4 parent: 97244:527f1bbf1840 user: Yury Selivanov date: Tue Aug 04 15:56:33 2015 -0400 summary: asyncio: Sync with upstream (compat module) files: Lib/asyncio/base_events.py | 3 ++- Lib/asyncio/base_subprocess.py | 4 ++-- Lib/asyncio/proactor_events.py | 4 ++-- Lib/asyncio/selector_events.py | 4 ++-- Lib/asyncio/sslproto.py | 4 ++-- Lib/asyncio/unix_events.py | 5 +++-- Lib/test/test_asyncio/test_subprocess.py | 6 +----- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -28,6 +28,7 @@ import sys import warnings +from . import compat from . import coroutines from . import events from . import futures @@ -378,7 +379,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self.is_closed(): warnings.warn("unclosed event loop %r" % self, ResourceWarning) diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -1,8 +1,8 @@ import collections import subprocess -import sys import warnings +from . import compat from . import futures from . import protocols from . import transports @@ -116,7 +116,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self._closed: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -7,10 +7,10 @@ __all__ = ['BaseProactorEventLoop'] import socket -import sys import warnings from . import base_events +from . import compat from . import constants from . import futures from . import sslproto @@ -79,7 +79,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._sock is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -10,7 +10,6 @@ import errno import functools import socket -import sys import warnings try: import ssl @@ -18,6 +17,7 @@ ssl = None from . import base_events +from . import compat from . import constants from . import events from . import futures @@ -568,7 +568,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._sock is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -1,11 +1,11 @@ import collections -import sys import warnings try: import ssl except ImportError: # pragma: no cover ssl = None +from . import compat from . import protocols from . import transports from .log import logger @@ -317,7 +317,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self._closed: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -13,6 +13,7 @@ from . import base_events from . import base_subprocess +from . import compat from . import constants from . import coroutines from . import events @@ -370,7 +371,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._pipe is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) @@ -555,7 +556,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._pipe is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,11 +417,7 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - if sys.platform == 'win32': - target = 'asyncio.windows_utils.Popen' - else: - target = 'subprocess.Popen' - with mock.patch(target) as popen: + with mock.patch('subprocess.Popen') as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:01:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 04 Aug 2015 20:01:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150804200132.23384.96949@psf.io> https://hg.python.org/cpython/rev/32765fa158b0 changeset: 97249:32765fa158b0 parent: 97246:6d9d3a866b2b parent: 97248:e3f381a3423d user: Yury Selivanov date: Tue Aug 04 15:57:05 2015 -0400 summary: Merge 3.5 files: Lib/asyncio/base_events.py | 3 ++- Lib/asyncio/base_subprocess.py | 4 ++-- Lib/asyncio/proactor_events.py | 4 ++-- Lib/asyncio/selector_events.py | 4 ++-- Lib/asyncio/sslproto.py | 4 ++-- Lib/asyncio/unix_events.py | 5 +++-- Lib/test/test_asyncio/test_subprocess.py | 6 +----- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -28,6 +28,7 @@ import sys import warnings +from . import compat from . import coroutines from . import events from . import futures @@ -378,7 +379,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self.is_closed(): warnings.warn("unclosed event loop %r" % self, ResourceWarning) diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -1,8 +1,8 @@ import collections import subprocess -import sys import warnings +from . import compat from . import futures from . import protocols from . import transports @@ -116,7 +116,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self._closed: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -7,10 +7,10 @@ __all__ = ['BaseProactorEventLoop'] import socket -import sys import warnings from . import base_events +from . import compat from . import constants from . import futures from . import sslproto @@ -79,7 +79,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._sock is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -10,7 +10,6 @@ import errno import functools import socket -import sys import warnings try: import ssl @@ -18,6 +17,7 @@ ssl = None from . import base_events +from . import compat from . import constants from . import events from . import futures @@ -568,7 +568,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._sock is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -1,11 +1,11 @@ import collections -import sys import warnings try: import ssl except ImportError: # pragma: no cover ssl = None +from . import compat from . import protocols from . import transports from .log import logger @@ -317,7 +317,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if not self._closed: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -13,6 +13,7 @@ from . import base_events from . import base_subprocess +from . import compat from . import constants from . import coroutines from . import events @@ -370,7 +371,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._pipe is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) @@ -555,7 +556,7 @@ # On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks # to the PEP 442. - if sys.version_info >= (3, 4): + if compat.PY34: def __del__(self): if self._pipe is not None: warnings.warn("unclosed transport %r" % self, ResourceWarning) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,11 +417,7 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - if sys.platform == 'win32': - target = 'asyncio.windows_utils.Popen' - else: - target = 'subprocess.Popen' - with mock.patch(target) as popen: + with mock.patch('subprocess.Popen') as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:16:54 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 20:16:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNzY5?= =?utf-8?q?=3A_Improve_reload=28=29_docs=2E_Patch_by_Dorian_Pula=2E?= Message-ID: <20150804201654.29392.89753@psf.io> https://hg.python.org/cpython/rev/cfd768814ca3 changeset: 97250:cfd768814ca3 branch: 2.7 parent: 97224:0511b1165bb6 user: Robert Collins date: Wed Aug 05 08:16:41 2015 +1200 summary: Issue #20769: Improve reload() docs. Patch by Dorian Pula. files: Doc/library/functions.rst | 9 +++++---- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1191,10 +1191,11 @@ except NameError: cache = {} - It is legal though generally not very useful to reload built-in or dynamically - loaded modules, except for :mod:`sys`, :mod:`__main__` and :mod:`__builtin__`. - In many cases, however, extension modules are not designed to be initialized - more than once, and may fail in arbitrary ways when reloaded. + It is generally not very useful to reload built-in or dynamically loaded + modules. Reloading :mod:`sys`, :mod:`__main__`, :mod:`builtins` and other + key modules is not recommended. In many cases extension modules are not + designed to be initialized more than once, and may fail in arbitrary ways + when reloaded. If a module imports objects from another module using :keyword:`from` ... :keyword:`import` ..., calling :func:`reload` for the other module does not diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1088,6 +1088,7 @@ Donovan Preston Paul Price Iuliia Proskurnia +Dorian Pula Jyrki Pulliainen Steve Purcell Eduardo P?rez diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -142,6 +142,8 @@ Documentation ------------- +- Issue #20769: Improve reload() docs. Patch by Dorian Pula. + - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. - Issue #22155: Add File Handlers subsection with createfilehandler to Tkinter -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:32:37 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 20:32:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIwNzY5?= =?utf-8?q?=3A_Improve_reload=28=29_docs=2E_Patch_by_Dorian_Pula=2E?= Message-ID: <20150804203237.111078.36803@psf.io> https://hg.python.org/cpython/rev/33dfbb293892 changeset: 97251:33dfbb293892 branch: 3.4 parent: 97247:99550a01fa6e user: Robert Collins date: Wed Aug 05 08:20:53 2015 +1200 summary: Issue #20769: Improve reload() docs. Patch by Dorian Pula. files: Doc/library/importlib.rst | 10 +++++----- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -166,11 +166,11 @@ except NameError: cache = {} - It is legal though generally not very useful to reload built-in or - dynamically loaded modules (this is not true for e.g. :mod:`sys`, - :mod:`__main__`, :mod:`builtins` and other key modules where reloading is - frowned upon). In many cases, however, extension modules are not designed to - be initialized more than once, and may fail in arbitrary ways when reloaded. + It is generally not very useful to reload built-in or dynamically loaded + modules. Reloading :mod:`sys`, :mod:`__main__`, :mod:`builtins` and other + key modules is not recommended. In many cases extension modules are not + designed to be initialized more than once, and may fail in arbitrary ways + when reloaded. If a module imports objects from another module using :keyword:`from` ... :keyword:`import` ..., calling :func:`reload` for the other module does not diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1098,6 +1098,7 @@ Donovan Preston Paul Price Iuliia Proskurnia +Dorian Pula Jyrki Pulliainen Steve Purcell Eduardo P?rez diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -408,6 +408,8 @@ Documentation ------------- +- Issue #20769: Improve reload() docs. Patch by Dorian Pula. + - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. - Issue #24729: Correct IO tutorial to match implementation regarding -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:32:37 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 20:32:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320769=3A_Improve_reload=28=29_docs=2E_Patch_by_?= =?utf-8?q?Dorian_Pula=2E?= Message-ID: <20150804203237.29412.38496@psf.io> https://hg.python.org/cpython/rev/6778332f687a changeset: 97253:6778332f687a parent: 97249:32765fa158b0 parent: 97252:9fe1a440e4b8 user: Robert Collins date: Wed Aug 05 08:32:11 2015 +1200 summary: Issue #20769: Improve reload() docs. Patch by Dorian Pula. files: Doc/library/importlib.rst | 10 +++++----- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -179,11 +179,11 @@ except NameError: cache = {} - It is legal though generally not very useful to reload built-in or - dynamically loaded modules (this is not true for e.g. :mod:`sys`, - :mod:`__main__`, :mod:`builtins` and other key modules where reloading is - frowned upon). In many cases, however, extension modules are not designed to - be initialized more than once, and may fail in arbitrary ways when reloaded. + It is generally not very useful to reload built-in or dynamically loaded + modules. Reloading :mod:`sys`, :mod:`__main__`, :mod:`builtins` and other + key modules is not recommended. In many cases extension modules are not + designed to be initialized more than once, and may fail in arbitrary ways + when reloaded. If a module imports objects from another module using :keyword:`from` ... :keyword:`import` ..., calling :func:`reload` for the other module does not diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1127,6 +1127,7 @@ Donovan Preston Paul Price Iuliia Proskurnia +Dorian Pula Jyrki Pulliainen Steve Purcell Eduardo P?rez diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,8 @@ Documentation ------------- +- Issue #20769: Improve reload() docs. Patch by Dorian Pula. + - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. - Issue #24729: Correct IO tutorial to match implementation regarding -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 4 22:32:37 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 04 Aug 2015 20:32:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2320769=3A_Improve_reload=28=29_docs=2E_Patch_by_Dorian?= =?utf-8?q?_Pula=2E?= Message-ID: <20150804203237.41833.57054@psf.io> https://hg.python.org/cpython/rev/9fe1a440e4b8 changeset: 97252:9fe1a440e4b8 branch: 3.5 parent: 97248:e3f381a3423d parent: 97251:33dfbb293892 user: Robert Collins date: Wed Aug 05 08:28:53 2015 +1200 summary: Issue #20769: Improve reload() docs. Patch by Dorian Pula. files: Doc/library/importlib.rst | 10 +++++----- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -179,11 +179,11 @@ except NameError: cache = {} - It is legal though generally not very useful to reload built-in or - dynamically loaded modules (this is not true for e.g. :mod:`sys`, - :mod:`__main__`, :mod:`builtins` and other key modules where reloading is - frowned upon). In many cases, however, extension modules are not designed to - be initialized more than once, and may fail in arbitrary ways when reloaded. + It is generally not very useful to reload built-in or dynamically loaded + modules. Reloading :mod:`sys`, :mod:`__main__`, :mod:`builtins` and other + key modules is not recommended. In many cases extension modules are not + designed to be initialized more than once, and may fail in arbitrary ways + when reloaded. If a module imports objects from another module using :keyword:`from` ... :keyword:`import` ..., calling :func:`reload` for the other module does not diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1127,6 +1127,7 @@ Donovan Preston Paul Price Iuliia Proskurnia +Dorian Pula Jyrki Pulliainen Steve Purcell Eduardo P?rez diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,8 @@ Documentation ------------- +- Issue #20769: Improve reload() docs. Patch by Dorian Pula. + - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. - Issue #24729: Correct IO tutorial to match implementation regarding -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 01:03:38 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 04 Aug 2015 23:03:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Puts_compiled_?= =?utf-8?q?pyc_files_into_embedded_library_ZIP_file_instead_of_sources=2E?= Message-ID: <20150804230338.29414.10629@psf.io> https://hg.python.org/cpython/rev/984c4532f6f4 changeset: 97254:984c4532f6f4 branch: 3.5 parent: 97252:9fe1a440e4b8 user: Steve Dower date: Tue Aug 04 16:02:40 2015 -0700 summary: Puts compiled pyc files into embedded library ZIP file instead of sources. files: Tools/msi/make_zip.py | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -1,4 +1,5 @@ import argparse +import py_compile import re import sys import shutil @@ -82,7 +83,16 @@ with ZipFile(str(target), 'w', ZIP_DEFLATED) as f: for s, rel in rel_sources: - f.write(str(s), str(rel)) + if rel.suffix.lower() == '.py': + pyc = Path(tempfile.gettempdir()) / rel.with_suffix('.pyc').name + try: + py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) + except py_compile.PyCompileError: + f.write(str(s), str(rel)) + else: + f.write(str(pyc), str(rel.with_suffix('.pyc'))) + else: + f.write(str(s), str(rel)) count += 1 else: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 01:03:42 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 04 Aug 2015 23:03:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Puts_compiled_pyc_files_into_embedded_library_ZIP_file_i?= =?utf-8?q?nstead_of_sources=2E?= Message-ID: <20150804230338.23394.37294@psf.io> https://hg.python.org/cpython/rev/7c68d5d30441 changeset: 97255:7c68d5d30441 parent: 97253:6778332f687a parent: 97254:984c4532f6f4 user: Steve Dower date: Tue Aug 04 16:02:55 2015 -0700 summary: Puts compiled pyc files into embedded library ZIP file instead of sources. files: Tools/msi/make_zip.py | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -1,4 +1,5 @@ import argparse +import py_compile import re import sys import shutil @@ -82,7 +83,16 @@ with ZipFile(str(target), 'w', ZIP_DEFLATED) as f: for s, rel in rel_sources: - f.write(str(s), str(rel)) + if rel.suffix.lower() == '.py': + pyc = Path(tempfile.gettempdir()) / rel.with_suffix('.pyc').name + try: + py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) + except py_compile.PyCompileError: + f.write(str(s), str(rel)) + else: + f.write(str(pyc), str(rel.with_suffix('.pyc'))) + else: + f.write(str(s), str(rel)) count += 1 else: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 01:30:56 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 04 Aug 2015 23:30:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogRG9uJ3QgbGVmdCBz?= =?utf-8?q?hift_negative_values=2E__Use_an_unsigned_value_instead_to_avoid?= Message-ID: <20150804233052.110661.23491@psf.io> https://hg.python.org/cpython/rev/50ea0c4bfbee changeset: 97256:50ea0c4bfbee branch: 2.7 parent: 97250:cfd768814ca3 user: Gregory P. Smith date: Tue Aug 04 16:29:00 2015 -0700 summary: Don't left shift negative values. Use an unsigned value instead to avoid undefined behavior. files: Modules/cPickle.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/cPickle.c b/Modules/cPickle.c --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -3448,7 +3448,7 @@ * to extend a BININT's sign bit to the full width. */ if (x == 4 && l & (1L << 31)) - l |= (~0L) << 32; + l |= (~0UL) << 32; #endif return l; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:00:19 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:00:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NzUx?= =?utf-8?q?=3A_When_running_regrtest_with_=27-w=27=2C_don=27t_fail_if_re-r?= =?utf-8?q?un_succeeds=2E?= Message-ID: <20150805030016.41837.21381@psf.io> https://hg.python.org/cpython/rev/6987a9c7dde9 changeset: 97257:6987a9c7dde9 branch: 2.7 user: Zachary Ware date: Tue Aug 04 21:53:21 2015 -0500 summary: Issue #24751: When running regrtest with '-w', don't fail if re-run succeeds. files: Lib/test/regrtest.py | 11 ++++++++--- Misc/NEWS | 7 +++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -652,7 +652,7 @@ if verbose2 and bad: print "Re-running failed tests in verbose mode" - for test in bad: + for test in bad[:]: print "Re-running test %r in verbose mode" % test sys.stdout.flush() try: @@ -662,8 +662,13 @@ # print a newline separate from the ^C print break - except: - raise + else: + if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: + bad.remove(test) + else: + if bad: + print count(len(bad), "test"), "failed again:" + printlist(bad) if single: if next_single_test: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -149,6 +149,13 @@ - Issue #22155: Add File Handlers subsection with createfilehandler to Tkinter doc. Remove obsolete example from FAQ. Patch by Martin Panter. +Tests +----- + +- Issue #24751: When running regrtest with the ``-w`` command line option, + a test run is no longer marked as a failure if all tests succeed when + re-run. + What's New in Python 2.7.10? ============================ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:00:19 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:00:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzUx?= =?utf-8?q?=3A_When_running_regrtest_with_=27-w=27=2C_don=27t_fail_if_re-r?= =?utf-8?q?un_succeeds=2E?= Message-ID: <20150805030016.110864.27769@psf.io> https://hg.python.org/cpython/rev/9964edf2fd1e changeset: 97258:9964edf2fd1e branch: 3.4 parent: 97251:33dfbb293892 user: Zachary Ware date: Tue Aug 04 21:54:54 2015 -0500 summary: Issue #24751: When running regrtest with '-w', don't fail if re-run succeeds. files: Lib/test/regrtest.py | 11 ++++++++--- Misc/NEWS | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -812,7 +812,7 @@ if ns.verbose2 and bad: print("Re-running failed tests in verbose mode") - for test in bad: + for test in bad[:]: print("Re-running test %r in verbose mode" % test) sys.stdout.flush() try: @@ -823,8 +823,13 @@ # print a newline separate from the ^C print() break - except: - raise + else: + if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: + bad.remove(test) + else: + if bad: + print(count(len(bad), 'test'), "failed again:") + printlist(bad) if ns.single: if next_single_test: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -380,6 +380,10 @@ Tests ----- +- Issue #24751: When running regrtest with the ``-w`` command line option, + a test run is no longer marked as a failure if all tests succeed when + re-run. + - Issue #21520: test_zipfile no longer fails if the word 'bad' appears anywhere in the name of the current directory. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:00:19 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:00:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324751=3A_Merge_with_3=2E4?= Message-ID: <20150805030016.23400.10029@psf.io> https://hg.python.org/cpython/rev/9d1f6022261d changeset: 97259:9d1f6022261d branch: 3.5 parent: 97254:984c4532f6f4 parent: 97258:9964edf2fd1e user: Zachary Ware date: Tue Aug 04 21:58:00 2015 -0500 summary: Issue #24751: Merge with 3.4 files: Lib/test/regrtest.py | 9 ++++++++- Misc/NEWS | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -810,7 +810,7 @@ if ns.verbose2 and bad: print("Re-running failed tests in verbose mode") - for test in bad: + for test in bad[:]: print("Re-running test %r in verbose mode" % test) sys.stdout.flush() try: @@ -821,6 +821,13 @@ # print a newline separate from the ^C print() break + else: + if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: + bad.remove(test) + else: + if bad: + print(count(len(bad), 'test'), "failed again:") + printlist(bad) if ns.single: if next_single_test: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,13 @@ - Issue #24729: Correct IO tutorial to match implementation regarding encoding parameter to open function. +Tests +----- + +- Issue #24751: When running regrtest with the ``-w`` command line option, + a test run is no longer marked as a failure if all tests succeed when + re-run. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:00:19 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:00:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2324751=3A_Merge_with_3=2E5?= Message-ID: <20150805030016.29416.94318@psf.io> https://hg.python.org/cpython/rev/6f67c74608b6 changeset: 97260:6f67c74608b6 parent: 97255:7c68d5d30441 parent: 97259:9d1f6022261d user: Zachary Ware date: Tue Aug 04 21:59:09 2015 -0500 summary: Closes #24751: Merge with 3.5 files: Lib/test/regrtest.py | 9 ++++++++- Misc/NEWS | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -810,7 +810,7 @@ if ns.verbose2 and bad: print("Re-running failed tests in verbose mode") - for test in bad: + for test in bad[:]: print("Re-running test %r in verbose mode" % test) sys.stdout.flush() try: @@ -821,6 +821,13 @@ # print a newline separate from the ^C print() break + else: + if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: + bad.remove(test) + else: + if bad: + print(count(len(bad), 'test'), "failed again:") + printlist(bad) if ns.single: if next_single_test: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,13 @@ - Issue #24729: Correct IO tutorial to match implementation regarding encoding parameter to open function. +Tests +----- + +- Issue #24751: When running regrtest with the ``-w`` command line option, + a test run is no longer marked as a failure if all tests succeed when + re-run. + What's New in Python 3.5.0 beta 4? ================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:53:24 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:53:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150805035324.5533.34913@psf.io> https://hg.python.org/cpython/rev/643b332465d7 changeset: 97263:643b332465d7 parent: 97260:6f67c74608b6 parent: 97262:565148a084b1 user: Zachary Ware date: Tue Aug 04 22:51:39 2015 -0500 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:53:24 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:53:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Nzkx?= =?utf-8?q?=3A_Add_tests_for_things_that_regressed_with_PEP_448?= Message-ID: <20150805035324.94778.32048@psf.io> https://hg.python.org/cpython/rev/3c170f68407f changeset: 97261:3c170f68407f branch: 3.4 parent: 97258:9964edf2fd1e user: Zachary Ware date: Tue Aug 04 22:49:55 2015 -0500 summary: Issue #24791: Add tests for things that regressed with PEP 448 files: Lib/test/test_grammar.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -204,7 +204,9 @@ d01() d01(1) d01(*(1,)) + d01(*[] or [2]) d01(**{'a':2}) + d01(**{'a':2} or {}) def d11(a, b=1): pass d11(1) d11(1, 2) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 05:53:24 2015 From: python-checkins at python.org (zach.ware) Date: Wed, 05 Aug 2015 03:53:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Null_merge?= Message-ID: <20150805035324.5515.25312@psf.io> https://hg.python.org/cpython/rev/565148a084b1 changeset: 97262:565148a084b1 branch: 3.5 parent: 97259:9d1f6022261d parent: 97261:3c170f68407f user: Zachary Ware date: Tue Aug 04 22:51:27 2015 -0500 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Wed Aug 5 10:02:38 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Wed, 5 Aug 2015 08:02:38 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-05 Message-ID: Results for project python_default-nightly, build date 2015-08-05 09:02:37 commit: 643b332465d71c03317ccfcf6c6b6f9140f0f627 revision date: 2015-08-05 06:51:39 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec -0.26316% -2.98081% :-( regex_v8 sec -0.76293% -3.74045% :-| nbody sec 0.08392% -0.44118% :-| json_dump_v2 sec -0.56179% -1.62920% :-| normal_startup sec 0.17321% 0.02197% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From solipsis at pitrou.net Wed Aug 5 10:46:02 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 05 Aug 2015 08:46:02 +0000 Subject: [Python-checkins] Daily reference leaks (643b332465d7): sum=4 Message-ID: <20150805084601.23390.81768@psf.io> results for 643b332465d7 on branch "default" -------------------------------------------- test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogUcuj5I', '--timeout', '7200'] From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fix_trailing_ws_=28merge_from_3=2E5=29=2E?= Message-ID: <20150805102739.1374.63182@psf.io> https://hg.python.org/cpython/rev/a9e6dd0fc9de changeset: 97271:a9e6dd0fc9de parent: 97269:69fcedc20baf parent: 97270:f0cdbc5d2cf3 user: Guido van Rossum date: Wed Aug 05 12:26:28 2015 +0200 summary: Fix trailing ws (merge from 3.5). files: Doc/library/typing.rst | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -47,8 +47,8 @@ on_error: Callable[[int, Exception], None]) -> None: # Body -It is possible to declare the return type of a callable without specifying -the call signature by substituting a literal ellipsis +It is possible to declare the return type of a callable without specifying +the call signature by substituting a literal ellipsis for the list of arguments in the type hint: `Callable[..., ReturnType]`. `None` as a type hint is a special case and is replaced by `type(None)`. @@ -182,7 +182,7 @@ Use a literal ellipsis `...` to declare an argument as having a default value:: from typing import AnyStr - + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... @@ -277,14 +277,14 @@ .. class:: Tuple - Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items with the first item of type X and the second of type Y. Example: `Tuple[T1, T2]` is a tuple of two elements corresponding to type variables T1 and T2. `Tuple[int, float, str]` is a tuple of an int, a float and a string. - To specify a variable-length tuple of homogeneous type, + To specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g. `Tuple[int, ...]`. .. class:: Callable @@ -296,9 +296,9 @@ must be a list of types; the return type must be a single type. There is no syntax to indicate optional or keyword arguments, - such function types are rarely used as callback types. - `Callable[..., ReturnType]` could be used to type hint a callable - taking any number of arguments and returning `ReturnType`. + such function types are rarely used as callback types. + `Callable[..., ReturnType]` could be used to type hint a callable + taking any number of arguments and returning `ReturnType`. A plain `Callable` is equivalent to `Callable[..., Any]`. .. class:: Generic @@ -322,7 +322,7 @@ try: return mapping[key] except KeyError: - return default + return default .. class:: Iterable(Generic[T_co]) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fix_trailing_w?= =?utf-8?q?s=2E?= Message-ID: <20150805102739.29388.24919@psf.io> https://hg.python.org/cpython/rev/f0cdbc5d2cf3 changeset: 97270:f0cdbc5d2cf3 branch: 3.5 parent: 97268:c8ac5dd318e2 user: Guido van Rossum date: Wed Aug 05 12:26:07 2015 +0200 summary: Fix trailing ws. files: Doc/library/typing.rst | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -47,8 +47,8 @@ on_error: Callable[[int, Exception], None]) -> None: # Body -It is possible to declare the return type of a callable without specifying -the call signature by substituting a literal ellipsis +It is possible to declare the return type of a callable without specifying +the call signature by substituting a literal ellipsis for the list of arguments in the type hint: `Callable[..., ReturnType]`. `None` as a type hint is a special case and is replaced by `type(None)`. @@ -182,7 +182,7 @@ Use a literal ellipsis `...` to declare an argument as having a default value:: from typing import AnyStr - + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... @@ -277,14 +277,14 @@ .. class:: Tuple - Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items with the first item of type X and the second of type Y. Example: `Tuple[T1, T2]` is a tuple of two elements corresponding to type variables T1 and T2. `Tuple[int, float, str]` is a tuple of an int, a float and a string. - To specify a variable-length tuple of homogeneous type, + To specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g. `Tuple[int, ...]`. .. class:: Callable @@ -296,9 +296,9 @@ must be a list of types; the return type must be a single type. There is no syntax to indicate optional or keyword arguments, - such function types are rarely used as callback types. - `Callable[..., ReturnType]` could be used to type hint a callable - taking any number of arguments and returning `ReturnType`. + such function types are rarely used as callback types. + `Callable[..., ReturnType]` could be used to type hint a callable + taking any number of arguments and returning `ReturnType`. A plain `Callable` is equivalent to `Callable[..., Any]`. .. class:: Generic @@ -322,7 +322,7 @@ try: return mapping[key] except KeyError: - return default + return default .. class:: Iterable(Generic[T_co]) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323973=3A_Update_typing=2Epy_from_GitHub_repo=2E?= =?utf-8?b?IChNZXJnZSBmcm9tIDMuNS4p?= Message-ID: <20150805102738.29414.656@psf.io> https://hg.python.org/cpython/rev/c9a6ce666ff2 changeset: 97267:c9a6ce666ff2 parent: 97263:643b332465d7 parent: 97266:f142b7c7a8e3 user: Guido van Rossum date: Wed Aug 05 12:13:11 2015 +0200 summary: Issue #23973: Update typing.py from GitHub repo. (Merge from 3.5.) files: Lib/test/test_typing.py | 24 +++++++++++ Lib/typing.py | 59 +++++++++++++++++++++++----- Misc/NEWS | 2 + 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -459,6 +459,14 @@ ctv = Callable[..., str] self.assertEqual(repr(ctv), 'typing.Callable[..., str]') + def test_callable_with_ellipsis(self): + + def foo(a: Callable[..., T]): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Callable[..., T]}) + XK = TypeVar('XK', str, bytes) XV = TypeVar('XV') @@ -555,6 +563,14 @@ with self.assertRaises(TypeError): Y[str, bytes] + def test_init(self): + T = TypeVar('T') + S = TypeVar('S') + with self.assertRaises(TypeError): + Generic[T, T] + with self.assertRaises(TypeError): + Generic[T, S, T] + def test_repr(self): self.assertEqual(repr(SimpleMapping), __name__ + '.' + 'SimpleMapping[~XK, ~XV]') @@ -801,6 +817,14 @@ self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': Callable[[T], T]}) + def test_callable_with_ellipsis_forward(self): + + def foo(a: 'Callable[..., T]'): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Callable[..., T]}) + def test_syntax_error(self): with self.assertRaises(SyntaxError): diff --git a/Lib/typing.py b/Lib/typing.py --- a/Lib/typing.py +++ b/Lib/typing.py @@ -128,6 +128,8 @@ class Final: """Mix-in class to prevent instantiation.""" + __slots__ = () + def __new__(self, *args, **kwds): raise TypeError("Cannot instantiate %r" % self.__class__) @@ -204,6 +206,8 @@ False. """ + __slots__ = ('name', 'type_var', 'impl_type', 'type_checker') + def __new__(cls, *args, **kwds): """Constructor. @@ -341,6 +345,8 @@ - As a special case, Any and object are subclasses of each other. """ + __slots__ = () + class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): """Type variable. @@ -635,6 +641,8 @@ Optional[X] is equivalent to Union[X, type(None)]. """ + __slots__ = () + class TupleMeta(TypingMeta): """Metaclass for Tuple.""" @@ -734,6 +742,8 @@ To specify a variable-length tuple of homogeneous type, use Sequence[T]. """ + __slots__ = () + class CallableMeta(TypingMeta): """Metaclass for Callable.""" @@ -767,7 +777,10 @@ def _eval_type(self, globalns, localns): if self.__args__ is None and self.__result__ is None: return self - args = [_eval_type(t, globalns, localns) for t in self.__args__] + if self.__args__ is Ellipsis: + args = self.__args__ + else: + args = [_eval_type(t, globalns, localns) for t in self.__args__] result = _eval_type(self.__result__, globalns, localns) if args == self.__args__ and result == self.__result__: return self @@ -837,6 +850,8 @@ such function types are rarely used as callback types. """ + __slots__ = () + def _gorg(a): """Return the farthest origin of a generic class.""" @@ -947,6 +962,8 @@ if not isinstance(p, TypeVar): raise TypeError("Initial parameters must be " "type variables; got %s" % p) + if len(set(params)) != len(params): + raise TypeError("All type variables in Generic[...] must be distinct.") else: if len(params) != len(self.__parameters__): raise TypeError("Cannot change parameter count from %d to %d" % @@ -1039,6 +1056,8 @@ # Same body as above. """ + __slots__ = () + def __new__(cls, *args, **kwds): next_in_mro = object # Look for the last occurrence of Generic or Generic[...]. @@ -1205,6 +1224,7 @@ attr != '__abstractmethods__' and attr != '_is_protocol' and attr != '__dict__' and + attr != '__slots__' and attr != '_get_protocol_attrs' and attr != '__parameters__' and attr != '__origin__' and @@ -1222,6 +1242,8 @@ such as Hashable). """ + __slots__ = () + _is_protocol = True @@ -1232,14 +1254,15 @@ class Iterable(Generic[T_co], extra=collections_abc.Iterable): - pass + __slots__ = () class Iterator(Iterable[T_co], extra=collections_abc.Iterator): - pass + __slots__ = () class SupportsInt(_Protocol): + __slots__ = () @abstractmethod def __int__(self) -> int: @@ -1247,6 +1270,7 @@ class SupportsFloat(_Protocol): + __slots__ = () @abstractmethod def __float__(self) -> float: @@ -1254,6 +1278,7 @@ class SupportsComplex(_Protocol): + __slots__ = () @abstractmethod def __complex__(self) -> complex: @@ -1261,30 +1286,34 @@ class SupportsBytes(_Protocol): + __slots__ = () @abstractmethod def __bytes__(self) -> bytes: pass -class SupportsAbs(_Protocol[T]): +class SupportsAbs(_Protocol[T_co]): + __slots__ = () @abstractmethod - def __abs__(self) -> T: + def __abs__(self) -> T_co: pass -class SupportsRound(_Protocol[T]): +class SupportsRound(_Protocol[T_co]): + __slots__ = () @abstractmethod - def __round__(self, ndigits: int = 0) -> T: + def __round__(self, ndigits: int = 0) -> T_co: pass -class Reversible(_Protocol[T]): +class Reversible(_Protocol[T_co]): + __slots__ = () @abstractmethod - def __reversed__(self) -> 'Iterator[T]': + def __reversed__(self) -> 'Iterator[T_co]': pass @@ -1292,7 +1321,7 @@ class Container(Generic[T_co], extra=collections_abc.Container): - pass + __slots__ = () # Callable was defined earlier. @@ -1308,7 +1337,7 @@ # NOTE: Only the value type is covariant. -class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co], +class Mapping(Sized, Iterable[KT], Container[KT], Generic[VT_co], extra=collections_abc.Mapping): pass @@ -1366,6 +1395,7 @@ class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta): + __slots__ = () def __new__(cls, *args, **kwds): if _geqv(cls, FrozenSet): @@ -1413,6 +1443,7 @@ class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co], extra=_G_base): + __slots__ = () def __new__(cls, *args, **kwds): if _geqv(cls, Generator): @@ -1456,6 +1487,8 @@ way to track the other distinctions in the type system. """ + __slots__ = () + @abstractproperty def mode(self) -> str: pass @@ -1540,6 +1573,8 @@ class BinaryIO(IO[bytes]): """Typed version of the return of open() in binary mode.""" + __slots__ = () + @abstractmethod def write(self, s: Union[bytes, bytearray]) -> int: pass @@ -1552,6 +1587,8 @@ class TextIO(IO[str]): """Typed version of the return of open() in text mode.""" + __slots__ = () + @abstractproperty def buffer(self) -> BinaryIO: pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #23973: Update typing.py from GitHub repo. + - Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. - Issue #23652: Make it possible to compile the select module against the -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge_docs_for_typing=2Epy_from_accidental_branch=2E?= Message-ID: <20150805102739.53989.39821@psf.io> https://hg.python.org/cpython/rev/c8ac5dd318e2 changeset: 97268:c8ac5dd318e2 branch: 3.5 parent: 97266:f142b7c7a8e3 parent: 97264:a8dcbd2711d6 user: Guido van Rossum date: Wed Aug 05 12:21:40 2015 +0200 summary: Merge docs for typing.py from accidental branch. files: Doc/library/typing.rst | 415 +++++++++++++++++++++++++++++ 1 files changed, 415 insertions(+), 0 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -13,3 +13,418 @@ :class:`Tuple`, :class:`Callable`, :class:`TypeVar`, and :class:`Generic`. For full specification please see :pep:`484`. For a simplified introduction to type hints see :pep:`483`. + + +The function below takes and returns a string and is annotated as follows:: + + def greeting(name: str) -> str: + return 'Hello ' + name + +In the function `greeting`, the argument `name` is expected to by of type `str` +and the return type `str`. Subtypes are accepted as arguments. + +Type aliases +------------ + +A type alias is defined by assigning the type to the alias:: + + Vector = List[float] + +Callable +-------- + +Frameworks expecting callback functions of specific signatures might be +type hinted using `Callable[[Arg1Type, Arg2Type], ReturnType]`. + +For example:: + + from typing import Callable + + def feeder(get_next_item: Callable[[], str]) -> None: + # Body + + def async_query(on_success: Callable[[int], None], + on_error: Callable[[int, Exception], None]) -> None: + # Body + +It is possible to declare the return type of a callable without specifying +the call signature by substituting a literal ellipsis +for the list of arguments in the type hint: `Callable[..., ReturnType]`. +`None` as a type hint is a special case and is replaced by `type(None)`. + +Generics +-------- + +Since type information about objects kept in containers cannot be statically +inferred in a generic way, abstract base classes have been extended to support +subscription to denote expected types for container elements. + +.. code-block:: python + + from typing import Mapping, Sequence + + def notify_by_email(employees: Sequence[Employee], + overrides: Mapping[str, str]) -> None: ... + +Generics can be parametrized by using a new factory available in typing +called TypeVar. + +.. code-block:: python + + from typing import Sequence, TypeVar + + T = TypeVar('T') # Declare type variable + + def first(l: Sequence[T]) -> T: # Generic function + return l[0] + + +User-defined generic types +-------------------------- + +A user-defined class can be defined as a generic class. + +.. code-block:: python + + from typing import TypeVar, Generic + from logging import Logger + + T = TypeVar('T') + + class LoggedVar(Generic[T]): + def __init__(self, value: T, name: str, logger: Logger) -> None: + self.name = name + self.logger = logger + self.value = value + + def set(self, new: T) -> None: + self.log('Set ' + repr(self.value)) + self.value = new + + def get(self) -> T: + self.log('Get ' + repr(self.value)) + return self.value + + def log(self, message: str) -> None: + self.logger.info('{}: {}'.format(self.name, message)) + +`Generic[T]` as a base class defines that the class `LoggedVar` takes a single +type parameter `T` . This also makes `T` valid as a type within the class body. + +The `Generic` base class uses a metaclass that defines `__getitem__` so that +`LoggedVar[t]` is valid as a type:: + + from typing import Iterable + + def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: + for var in vars: + var.set(0) + +A generic type can have any number of type variables, and type variables may +be constrained:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + S = TypeVar('S', int, str) + + class StrangePair(Generic[T, S]): + ... + +Each type variable argument to `Generic` must be distinct. +This is thus invalid:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + + class Pair(Generic[T, T]): # INVALID + ... + +You can use multiple inheritance with `Generic`:: + + from typing import TypeVar, Generic, Sized + + T = TypeVar('T') + + class LinkedList(Sized, Generic[T]): + ... + +Subclassing a generic class without specifying type parameters assumes `Any` +for each position. In the following example, `MyIterable` is not generic but +implicitly inherits from `Iterable[Any]`:: + + from typing import Iterable + + class MyIterable(Iterable): # Same as Iterable[Any] + +Generic metaclasses are not supported. + +The `Any` type +-------------- + +A special kind of type is `Any`. Every type is a subtype of `Any`. +This is also true for the builtin type object. However, to the static type +checker these are completely different. + +When the type of a value is `object`, the type checker will reject almost all +operations on it, and assigning it to a variable (or using it as a return value) +of a more specialized type is a type error. On the other hand, when a value has +type `Any`, the type checker will allow all operations on it, and a value of +type `Any` can be assigned to a variable (or used as a return value) of a more +constrained type. + +Default argument values +----------------------- + +Use a literal ellipsis `...` to declare an argument as having a default value:: + + from typing import AnyStr + + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... + + +Classes, functions, and decorators +---------------------------------- + +The module defines the following classes, functions and decorators: + +.. class:: Any + + Special type indicating an unconstrained type. + + * Any object is an instance of `Any`. + * Any class is a subclass of `Any`. + * As a special case, `Any` and `object` are subclasses of each other. + +.. class:: TypeVar + + Type variable. + + Usage:: + + T = TypeVar('T') # Can be anything + A = TypeVar('A', str, bytes) # Must be str or bytes + + Type variables exist primarily for the benefit of static type + checkers. They serve as the parameters for generic types as well + as for generic function definitions. See class Generic for more + information on generic types. Generic functions work as follows: + + .. code-block:: python + + def repeat(x: T, n: int) -> Sequence[T]: + """Return a list containing n references to x.""" + return [x]*n + + def longest(x: A, y: A) -> A: + """Return the longest of two strings.""" + return x if len(x) >= len(y) else y + + The latter example's signature is essentially the overloading + of `(str, str) -> str` and `(bytes, bytes) -> bytes`. Also note + that if the arguments are instances of some subclass of `str`, + the return type is still plain `str`. + + At runtime, `isinstance(x, T)` will raise `TypeError`. In general, + `isinstance` and `issublass` should not be used with types. + + Type variables may be marked covariant or contravariant by passing + `covariant=True` or `contravariant=True`. See :pep:`484` for more + details. By default type variables are invariant. + +.. class:: Union + + Union type; `Union[X, Y]` means either X or Y. + + To define a union, use e.g. `Union[int, str]`. Details: + + * The arguments must be types and there must be at least one. + + * Unions of unions are flattened, e.g.:: + + Union[Union[int, str], float] == Union[int, str, float] + + * Unions of a single argument vanish, e.g.:: + + Union[int] == int # The constructor actually returns int + + * Redundant arguments are skipped, e.g.:: + + Union[int, str, int] == Union[int, str] + + * When comparing unions, the argument order is ignored, e.g.:: + + Union[int, str] == Union[str, int] + + * If `Any` is present it is the sole survivor, e.g.:: + + Union[int, Any] == Any + + * You cannot subclass or instantiate a union. + + * You cannot write `Union[X][Y]` + + * You can use `Optional[X]` as a shorthand for `Union[X, None]`. + +.. class:: Optional + + Optional type. + + `Optional[X]` is equivalent to `Union[X, type(None)]`. + +.. class:: Tuple + + Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + with the first item of type X and the second of type Y. + + Example: `Tuple[T1, T2]` is a tuple of two elements corresponding + to type variables T1 and T2. `Tuple[int, float, str]` is a tuple + of an int, a float and a string. + + To specify a variable-length tuple of homogeneous type, + use literal ellipsis, e.g. `Tuple[int, ...]`. + +.. class:: Callable + + Callable type; `Callable[[int], str]` is a function of (int) -> str. + + The subscription syntax must always be used with exactly two + values: the argument list and the return type. The argument list + must be a list of types; the return type must be a single type. + + There is no syntax to indicate optional or keyword arguments, + such function types are rarely used as callback types. + `Callable[..., ReturnType]` could be used to type hint a callable + taking any number of arguments and returning `ReturnType`. + A plain `Callable` is equivalent to `Callable[..., Any]`. + +.. class:: Generic + + Abstract base class for generic types. + + A generic type is typically declared by inheriting from an + instantiation of this class with one or more type variables. + For example, a generic mapping type might be defined as:: + + class Mapping(Generic[KT, VT]): + def __getitem__(self, key: KT) -> VT: + ... + # Etc. + + This class can then be used as follows:: + + X = TypeVar('X') + Y = TypeVar('Y') + def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: + try: + return mapping[key] + except KeyError: + return default + +.. class:: Iterable(Generic[T_co]) + +.. class:: Iterator(Iterable[T_co]) + +.. class:: SupportsInt + +.. class:: SupportsFloat + +.. class:: SupportsAbs + +.. class:: SupportsRound + +.. class:: Reversible + +.. class:: Container(Generic[T_co]) + +.. class:: AbstractSet(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSet(AbstractSet[T]) + +.. class:: Mapping(Sized, Iterable[KT_co], Container[KT_co], Generic[KT_co, VT_co]) + +.. class:: MutableMapping(Mapping[KT, VT]) + +.. class:: Sequence(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSequence(Sequence[T]) + +.. class:: ByteString(Sequence[int]) + +.. class:: List(list, MutableSequence[T]) + +.. class:: Set(set, MutableSet[T]) + +.. class:: MappingView(Sized, Iterable[T_co]) + +.. class:: KeysView(MappingView[KT_co], AbstractSet[KT_co]) + +.. class:: ItemsView(MappingView, Generic[KT_co, VT_co]) + +.. class:: ValuesView(MappingView[VT_co]) + +.. class:: Dict(dict, MutableMapping[KT, VT]) + +.. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]) + +.. class:: io + + Wrapper namespace for IO generic classes. + +.. class:: re + + Wrapper namespace for re type classes. + +.. function:: NamedTuple(typename, fields) + + Typed version of namedtuple. + + Usage:: + + Employee = typing.NamedTuple('Employee', [('name', str), 'id', int)]) + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has one extra attribute: _field_types, + giving a dict mapping field names to types. (The field names + are in the _fields attribute, which is part of the namedtuple + API.) + +.. function:: cast(typ, val) + + Cast a value to a type. + + This returns the value unchanged. To the type checker this + signals that the return value has the designated type, but at + runtime we intentionally don't check anything (we want this + to be as fast as possible). + +.. function:: get_type_hints(obj) + + Return type hints for a function or method object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, and if necessary + adds Optional[t] if a default value equal to None is set. + +.. decorator:: no_type_check(arg) + + Decorator to indicate that annotations are not type hints. + + The argument must be a class or function; if it is a class, it + applies recursively to all methods defined in that class (but not + to methods defined in its superclasses or subclasses). + + This mutates the function(s) in place. + +.. decorator:: no_type_check_decorator(decorator) + + Decorator to give another decorator the @no_type_check effect. + + This wraps the decorator with something that wraps the decorated + function in @no_type_check. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_docs_for_typing=2Epy_from_3=2E5_into_default_branc?= =?utf-8?q?h=2E?= Message-ID: <20150805102739.23408.3441@psf.io> https://hg.python.org/cpython/rev/69fcedc20baf changeset: 97269:69fcedc20baf parent: 97267:c9a6ce666ff2 parent: 97265:0c74fd4219aa user: Guido van Rossum date: Wed Aug 05 12:24:21 2015 +0200 summary: Merge docs for typing.py from 3.5 into default branch. files: Doc/library/typing.rst | 415 +++++++++++++++++++++++++++++ 1 files changed, 415 insertions(+), 0 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -13,3 +13,418 @@ :class:`Tuple`, :class:`Callable`, :class:`TypeVar`, and :class:`Generic`. For full specification please see :pep:`484`. For a simplified introduction to type hints see :pep:`483`. + + +The function below takes and returns a string and is annotated as follows:: + + def greeting(name: str) -> str: + return 'Hello ' + name + +In the function `greeting`, the argument `name` is expected to by of type `str` +and the return type `str`. Subtypes are accepted as arguments. + +Type aliases +------------ + +A type alias is defined by assigning the type to the alias:: + + Vector = List[float] + +Callable +-------- + +Frameworks expecting callback functions of specific signatures might be +type hinted using `Callable[[Arg1Type, Arg2Type], ReturnType]`. + +For example:: + + from typing import Callable + + def feeder(get_next_item: Callable[[], str]) -> None: + # Body + + def async_query(on_success: Callable[[int], None], + on_error: Callable[[int, Exception], None]) -> None: + # Body + +It is possible to declare the return type of a callable without specifying +the call signature by substituting a literal ellipsis +for the list of arguments in the type hint: `Callable[..., ReturnType]`. +`None` as a type hint is a special case and is replaced by `type(None)`. + +Generics +-------- + +Since type information about objects kept in containers cannot be statically +inferred in a generic way, abstract base classes have been extended to support +subscription to denote expected types for container elements. + +.. code-block:: python + + from typing import Mapping, Sequence + + def notify_by_email(employees: Sequence[Employee], + overrides: Mapping[str, str]) -> None: ... + +Generics can be parametrized by using a new factory available in typing +called TypeVar. + +.. code-block:: python + + from typing import Sequence, TypeVar + + T = TypeVar('T') # Declare type variable + + def first(l: Sequence[T]) -> T: # Generic function + return l[0] + + +User-defined generic types +-------------------------- + +A user-defined class can be defined as a generic class. + +.. code-block:: python + + from typing import TypeVar, Generic + from logging import Logger + + T = TypeVar('T') + + class LoggedVar(Generic[T]): + def __init__(self, value: T, name: str, logger: Logger) -> None: + self.name = name + self.logger = logger + self.value = value + + def set(self, new: T) -> None: + self.log('Set ' + repr(self.value)) + self.value = new + + def get(self) -> T: + self.log('Get ' + repr(self.value)) + return self.value + + def log(self, message: str) -> None: + self.logger.info('{}: {}'.format(self.name, message)) + +`Generic[T]` as a base class defines that the class `LoggedVar` takes a single +type parameter `T` . This also makes `T` valid as a type within the class body. + +The `Generic` base class uses a metaclass that defines `__getitem__` so that +`LoggedVar[t]` is valid as a type:: + + from typing import Iterable + + def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: + for var in vars: + var.set(0) + +A generic type can have any number of type variables, and type variables may +be constrained:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + S = TypeVar('S', int, str) + + class StrangePair(Generic[T, S]): + ... + +Each type variable argument to `Generic` must be distinct. +This is thus invalid:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + + class Pair(Generic[T, T]): # INVALID + ... + +You can use multiple inheritance with `Generic`:: + + from typing import TypeVar, Generic, Sized + + T = TypeVar('T') + + class LinkedList(Sized, Generic[T]): + ... + +Subclassing a generic class without specifying type parameters assumes `Any` +for each position. In the following example, `MyIterable` is not generic but +implicitly inherits from `Iterable[Any]`:: + + from typing import Iterable + + class MyIterable(Iterable): # Same as Iterable[Any] + +Generic metaclasses are not supported. + +The `Any` type +-------------- + +A special kind of type is `Any`. Every type is a subtype of `Any`. +This is also true for the builtin type object. However, to the static type +checker these are completely different. + +When the type of a value is `object`, the type checker will reject almost all +operations on it, and assigning it to a variable (or using it as a return value) +of a more specialized type is a type error. On the other hand, when a value has +type `Any`, the type checker will allow all operations on it, and a value of +type `Any` can be assigned to a variable (or used as a return value) of a more +constrained type. + +Default argument values +----------------------- + +Use a literal ellipsis `...` to declare an argument as having a default value:: + + from typing import AnyStr + + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... + + +Classes, functions, and decorators +---------------------------------- + +The module defines the following classes, functions and decorators: + +.. class:: Any + + Special type indicating an unconstrained type. + + * Any object is an instance of `Any`. + * Any class is a subclass of `Any`. + * As a special case, `Any` and `object` are subclasses of each other. + +.. class:: TypeVar + + Type variable. + + Usage:: + + T = TypeVar('T') # Can be anything + A = TypeVar('A', str, bytes) # Must be str or bytes + + Type variables exist primarily for the benefit of static type + checkers. They serve as the parameters for generic types as well + as for generic function definitions. See class Generic for more + information on generic types. Generic functions work as follows: + + .. code-block:: python + + def repeat(x: T, n: int) -> Sequence[T]: + """Return a list containing n references to x.""" + return [x]*n + + def longest(x: A, y: A) -> A: + """Return the longest of two strings.""" + return x if len(x) >= len(y) else y + + The latter example's signature is essentially the overloading + of `(str, str) -> str` and `(bytes, bytes) -> bytes`. Also note + that if the arguments are instances of some subclass of `str`, + the return type is still plain `str`. + + At runtime, `isinstance(x, T)` will raise `TypeError`. In general, + `isinstance` and `issublass` should not be used with types. + + Type variables may be marked covariant or contravariant by passing + `covariant=True` or `contravariant=True`. See :pep:`484` for more + details. By default type variables are invariant. + +.. class:: Union + + Union type; `Union[X, Y]` means either X or Y. + + To define a union, use e.g. `Union[int, str]`. Details: + + * The arguments must be types and there must be at least one. + + * Unions of unions are flattened, e.g.:: + + Union[Union[int, str], float] == Union[int, str, float] + + * Unions of a single argument vanish, e.g.:: + + Union[int] == int # The constructor actually returns int + + * Redundant arguments are skipped, e.g.:: + + Union[int, str, int] == Union[int, str] + + * When comparing unions, the argument order is ignored, e.g.:: + + Union[int, str] == Union[str, int] + + * If `Any` is present it is the sole survivor, e.g.:: + + Union[int, Any] == Any + + * You cannot subclass or instantiate a union. + + * You cannot write `Union[X][Y]` + + * You can use `Optional[X]` as a shorthand for `Union[X, None]`. + +.. class:: Optional + + Optional type. + + `Optional[X]` is equivalent to `Union[X, type(None)]`. + +.. class:: Tuple + + Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + with the first item of type X and the second of type Y. + + Example: `Tuple[T1, T2]` is a tuple of two elements corresponding + to type variables T1 and T2. `Tuple[int, float, str]` is a tuple + of an int, a float and a string. + + To specify a variable-length tuple of homogeneous type, + use literal ellipsis, e.g. `Tuple[int, ...]`. + +.. class:: Callable + + Callable type; `Callable[[int], str]` is a function of (int) -> str. + + The subscription syntax must always be used with exactly two + values: the argument list and the return type. The argument list + must be a list of types; the return type must be a single type. + + There is no syntax to indicate optional or keyword arguments, + such function types are rarely used as callback types. + `Callable[..., ReturnType]` could be used to type hint a callable + taking any number of arguments and returning `ReturnType`. + A plain `Callable` is equivalent to `Callable[..., Any]`. + +.. class:: Generic + + Abstract base class for generic types. + + A generic type is typically declared by inheriting from an + instantiation of this class with one or more type variables. + For example, a generic mapping type might be defined as:: + + class Mapping(Generic[KT, VT]): + def __getitem__(self, key: KT) -> VT: + ... + # Etc. + + This class can then be used as follows:: + + X = TypeVar('X') + Y = TypeVar('Y') + def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: + try: + return mapping[key] + except KeyError: + return default + +.. class:: Iterable(Generic[T_co]) + +.. class:: Iterator(Iterable[T_co]) + +.. class:: SupportsInt + +.. class:: SupportsFloat + +.. class:: SupportsAbs + +.. class:: SupportsRound + +.. class:: Reversible + +.. class:: Container(Generic[T_co]) + +.. class:: AbstractSet(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSet(AbstractSet[T]) + +.. class:: Mapping(Sized, Iterable[KT_co], Container[KT_co], Generic[KT_co, VT_co]) + +.. class:: MutableMapping(Mapping[KT, VT]) + +.. class:: Sequence(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSequence(Sequence[T]) + +.. class:: ByteString(Sequence[int]) + +.. class:: List(list, MutableSequence[T]) + +.. class:: Set(set, MutableSet[T]) + +.. class:: MappingView(Sized, Iterable[T_co]) + +.. class:: KeysView(MappingView[KT_co], AbstractSet[KT_co]) + +.. class:: ItemsView(MappingView, Generic[KT_co, VT_co]) + +.. class:: ValuesView(MappingView[VT_co]) + +.. class:: Dict(dict, MutableMapping[KT, VT]) + +.. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]) + +.. class:: io + + Wrapper namespace for IO generic classes. + +.. class:: re + + Wrapper namespace for re type classes. + +.. function:: NamedTuple(typename, fields) + + Typed version of namedtuple. + + Usage:: + + Employee = typing.NamedTuple('Employee', [('name', str), 'id', int)]) + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has one extra attribute: _field_types, + giving a dict mapping field names to types. (The field names + are in the _fields attribute, which is part of the namedtuple + API.) + +.. function:: cast(typ, val) + + Cast a value to a type. + + This returns the value unchanged. To the type checker this + signals that the return value has the designated type, but at + runtime we intentionally don't check anything (we want this + to be as fast as possible). + +.. function:: get_type_hints(obj) + + Return type hints for a function or method object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, and if necessary + adds Optional[t] if a default value equal to None is set. + +.. decorator:: no_type_check(arg) + + Decorator to indicate that annotations are not type hints. + + The argument must be a class or function; if it is a class, it + applies recursively to all methods defined in that class (but not + to methods defined in its superclasses or subclasses). + + This mutates the function(s) in place. + +.. decorator:: no_type_check_decorator(decorator) + + Decorator to give another decorator the @no_type_check effect. + + This wraps the decorator with something that wraps the decorated + function in @no_type_check. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324272=3A_Initial_docs_for_typing=2Epy_=28PEP_48?= =?utf-8?b?NCkuIChNZXJnZSBmcm9tIDMuNS4p?= Message-ID: <20150805102738.53985.34030@psf.io> https://hg.python.org/cpython/rev/0c74fd4219aa changeset: 97265:0c74fd4219aa parent: 97220:5a13a3f3bb3b parent: 97264:a8dcbd2711d6 user: Guido van Rossum date: Mon Aug 03 22:39:12 2015 +0200 summary: Issue #24272: Initial docs for typing.py (PEP 484). (Merge from 3.5.) By Daniel Andrade Groppe and Ivan Levkivskyi. files: Doc/library/typing.rst | 415 +++++++++++++++++++++++++++++ 1 files changed, 415 insertions(+), 0 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -13,3 +13,418 @@ :class:`Tuple`, :class:`Callable`, :class:`TypeVar`, and :class:`Generic`. For full specification please see :pep:`484`. For a simplified introduction to type hints see :pep:`483`. + + +The function below takes and returns a string and is annotated as follows:: + + def greeting(name: str) -> str: + return 'Hello ' + name + +In the function `greeting`, the argument `name` is expected to by of type `str` +and the return type `str`. Subtypes are accepted as arguments. + +Type aliases +------------ + +A type alias is defined by assigning the type to the alias:: + + Vector = List[float] + +Callable +-------- + +Frameworks expecting callback functions of specific signatures might be +type hinted using `Callable[[Arg1Type, Arg2Type], ReturnType]`. + +For example:: + + from typing import Callable + + def feeder(get_next_item: Callable[[], str]) -> None: + # Body + + def async_query(on_success: Callable[[int], None], + on_error: Callable[[int, Exception], None]) -> None: + # Body + +It is possible to declare the return type of a callable without specifying +the call signature by substituting a literal ellipsis +for the list of arguments in the type hint: `Callable[..., ReturnType]`. +`None` as a type hint is a special case and is replaced by `type(None)`. + +Generics +-------- + +Since type information about objects kept in containers cannot be statically +inferred in a generic way, abstract base classes have been extended to support +subscription to denote expected types for container elements. + +.. code-block:: python + + from typing import Mapping, Sequence + + def notify_by_email(employees: Sequence[Employee], + overrides: Mapping[str, str]) -> None: ... + +Generics can be parametrized by using a new factory available in typing +called TypeVar. + +.. code-block:: python + + from typing import Sequence, TypeVar + + T = TypeVar('T') # Declare type variable + + def first(l: Sequence[T]) -> T: # Generic function + return l[0] + + +User-defined generic types +-------------------------- + +A user-defined class can be defined as a generic class. + +.. code-block:: python + + from typing import TypeVar, Generic + from logging import Logger + + T = TypeVar('T') + + class LoggedVar(Generic[T]): + def __init__(self, value: T, name: str, logger: Logger) -> None: + self.name = name + self.logger = logger + self.value = value + + def set(self, new: T) -> None: + self.log('Set ' + repr(self.value)) + self.value = new + + def get(self) -> T: + self.log('Get ' + repr(self.value)) + return self.value + + def log(self, message: str) -> None: + self.logger.info('{}: {}'.format(self.name, message)) + +`Generic[T]` as a base class defines that the class `LoggedVar` takes a single +type parameter `T` . This also makes `T` valid as a type within the class body. + +The `Generic` base class uses a metaclass that defines `__getitem__` so that +`LoggedVar[t]` is valid as a type:: + + from typing import Iterable + + def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: + for var in vars: + var.set(0) + +A generic type can have any number of type variables, and type variables may +be constrained:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + S = TypeVar('S', int, str) + + class StrangePair(Generic[T, S]): + ... + +Each type variable argument to `Generic` must be distinct. +This is thus invalid:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + + class Pair(Generic[T, T]): # INVALID + ... + +You can use multiple inheritance with `Generic`:: + + from typing import TypeVar, Generic, Sized + + T = TypeVar('T') + + class LinkedList(Sized, Generic[T]): + ... + +Subclassing a generic class without specifying type parameters assumes `Any` +for each position. In the following example, `MyIterable` is not generic but +implicitly inherits from `Iterable[Any]`:: + + from typing import Iterable + + class MyIterable(Iterable): # Same as Iterable[Any] + +Generic metaclasses are not supported. + +The `Any` type +-------------- + +A special kind of type is `Any`. Every type is a subtype of `Any`. +This is also true for the builtin type object. However, to the static type +checker these are completely different. + +When the type of a value is `object`, the type checker will reject almost all +operations on it, and assigning it to a variable (or using it as a return value) +of a more specialized type is a type error. On the other hand, when a value has +type `Any`, the type checker will allow all operations on it, and a value of +type `Any` can be assigned to a variable (or used as a return value) of a more +constrained type. + +Default argument values +----------------------- + +Use a literal ellipsis `...` to declare an argument as having a default value:: + + from typing import AnyStr + + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... + + +Classes, functions, and decorators +---------------------------------- + +The module defines the following classes, functions and decorators: + +.. class:: Any + + Special type indicating an unconstrained type. + + * Any object is an instance of `Any`. + * Any class is a subclass of `Any`. + * As a special case, `Any` and `object` are subclasses of each other. + +.. class:: TypeVar + + Type variable. + + Usage:: + + T = TypeVar('T') # Can be anything + A = TypeVar('A', str, bytes) # Must be str or bytes + + Type variables exist primarily for the benefit of static type + checkers. They serve as the parameters for generic types as well + as for generic function definitions. See class Generic for more + information on generic types. Generic functions work as follows: + + .. code-block:: python + + def repeat(x: T, n: int) -> Sequence[T]: + """Return a list containing n references to x.""" + return [x]*n + + def longest(x: A, y: A) -> A: + """Return the longest of two strings.""" + return x if len(x) >= len(y) else y + + The latter example's signature is essentially the overloading + of `(str, str) -> str` and `(bytes, bytes) -> bytes`. Also note + that if the arguments are instances of some subclass of `str`, + the return type is still plain `str`. + + At runtime, `isinstance(x, T)` will raise `TypeError`. In general, + `isinstance` and `issublass` should not be used with types. + + Type variables may be marked covariant or contravariant by passing + `covariant=True` or `contravariant=True`. See :pep:`484` for more + details. By default type variables are invariant. + +.. class:: Union + + Union type; `Union[X, Y]` means either X or Y. + + To define a union, use e.g. `Union[int, str]`. Details: + + * The arguments must be types and there must be at least one. + + * Unions of unions are flattened, e.g.:: + + Union[Union[int, str], float] == Union[int, str, float] + + * Unions of a single argument vanish, e.g.:: + + Union[int] == int # The constructor actually returns int + + * Redundant arguments are skipped, e.g.:: + + Union[int, str, int] == Union[int, str] + + * When comparing unions, the argument order is ignored, e.g.:: + + Union[int, str] == Union[str, int] + + * If `Any` is present it is the sole survivor, e.g.:: + + Union[int, Any] == Any + + * You cannot subclass or instantiate a union. + + * You cannot write `Union[X][Y]` + + * You can use `Optional[X]` as a shorthand for `Union[X, None]`. + +.. class:: Optional + + Optional type. + + `Optional[X]` is equivalent to `Union[X, type(None)]`. + +.. class:: Tuple + + Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + with the first item of type X and the second of type Y. + + Example: `Tuple[T1, T2]` is a tuple of two elements corresponding + to type variables T1 and T2. `Tuple[int, float, str]` is a tuple + of an int, a float and a string. + + To specify a variable-length tuple of homogeneous type, + use literal ellipsis, e.g. `Tuple[int, ...]`. + +.. class:: Callable + + Callable type; `Callable[[int], str]` is a function of (int) -> str. + + The subscription syntax must always be used with exactly two + values: the argument list and the return type. The argument list + must be a list of types; the return type must be a single type. + + There is no syntax to indicate optional or keyword arguments, + such function types are rarely used as callback types. + `Callable[..., ReturnType]` could be used to type hint a callable + taking any number of arguments and returning `ReturnType`. + A plain `Callable` is equivalent to `Callable[..., Any]`. + +.. class:: Generic + + Abstract base class for generic types. + + A generic type is typically declared by inheriting from an + instantiation of this class with one or more type variables. + For example, a generic mapping type might be defined as:: + + class Mapping(Generic[KT, VT]): + def __getitem__(self, key: KT) -> VT: + ... + # Etc. + + This class can then be used as follows:: + + X = TypeVar('X') + Y = TypeVar('Y') + def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: + try: + return mapping[key] + except KeyError: + return default + +.. class:: Iterable(Generic[T_co]) + +.. class:: Iterator(Iterable[T_co]) + +.. class:: SupportsInt + +.. class:: SupportsFloat + +.. class:: SupportsAbs + +.. class:: SupportsRound + +.. class:: Reversible + +.. class:: Container(Generic[T_co]) + +.. class:: AbstractSet(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSet(AbstractSet[T]) + +.. class:: Mapping(Sized, Iterable[KT_co], Container[KT_co], Generic[KT_co, VT_co]) + +.. class:: MutableMapping(Mapping[KT, VT]) + +.. class:: Sequence(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSequence(Sequence[T]) + +.. class:: ByteString(Sequence[int]) + +.. class:: List(list, MutableSequence[T]) + +.. class:: Set(set, MutableSet[T]) + +.. class:: MappingView(Sized, Iterable[T_co]) + +.. class:: KeysView(MappingView[KT_co], AbstractSet[KT_co]) + +.. class:: ItemsView(MappingView, Generic[KT_co, VT_co]) + +.. class:: ValuesView(MappingView[VT_co]) + +.. class:: Dict(dict, MutableMapping[KT, VT]) + +.. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]) + +.. class:: io + + Wrapper namespace for IO generic classes. + +.. class:: re + + Wrapper namespace for re type classes. + +.. function:: NamedTuple(typename, fields) + + Typed version of namedtuple. + + Usage:: + + Employee = typing.NamedTuple('Employee', [('name', str), 'id', int)]) + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has one extra attribute: _field_types, + giving a dict mapping field names to types. (The field names + are in the _fields attribute, which is part of the namedtuple + API.) + +.. function:: cast(typ, val) + + Cast a value to a type. + + This returns the value unchanged. To the type checker this + signals that the return value has the designated type, but at + runtime we intentionally don't check anything (we want this + to be as fast as possible). + +.. function:: get_type_hints(obj) + + Return type hints for a function or method object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, and if necessary + adds Optional[t] if a default value equal to None is set. + +.. decorator:: no_type_check(arg) + + Decorator to indicate that annotations are not type hints. + + The argument must be a class or function; if it is a class, it + applies recursively to all methods defined in that class (but not + to methods defined in its superclasses or subclasses). + + This mutates the function(s) in place. + +.. decorator:: no_type_check_decorator(decorator) + + Decorator to give another decorator the @no_type_check effect. + + This wraps the decorator with something that wraps the decorated + function in @no_type_check. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjcy?= =?utf-8?q?=3A_Initial_docs_for_typing=2Epy_=28PEP_484=29=2E?= Message-ID: <20150805102738.53987.8709@psf.io> https://hg.python.org/cpython/rev/a8dcbd2711d6 changeset: 97264:a8dcbd2711d6 branch: 3.5 parent: 97219:0f2fc3e7816d user: Guido van Rossum date: Mon Aug 03 22:35:46 2015 +0200 summary: Issue #24272: Initial docs for typing.py (PEP 484). By Daniel Andrade Groppe and Ivan Levkivskyi. files: Doc/library/typing.rst | 415 +++++++++++++++++++++++++++++ 1 files changed, 415 insertions(+), 0 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -13,3 +13,418 @@ :class:`Tuple`, :class:`Callable`, :class:`TypeVar`, and :class:`Generic`. For full specification please see :pep:`484`. For a simplified introduction to type hints see :pep:`483`. + + +The function below takes and returns a string and is annotated as follows:: + + def greeting(name: str) -> str: + return 'Hello ' + name + +In the function `greeting`, the argument `name` is expected to by of type `str` +and the return type `str`. Subtypes are accepted as arguments. + +Type aliases +------------ + +A type alias is defined by assigning the type to the alias:: + + Vector = List[float] + +Callable +-------- + +Frameworks expecting callback functions of specific signatures might be +type hinted using `Callable[[Arg1Type, Arg2Type], ReturnType]`. + +For example:: + + from typing import Callable + + def feeder(get_next_item: Callable[[], str]) -> None: + # Body + + def async_query(on_success: Callable[[int], None], + on_error: Callable[[int, Exception], None]) -> None: + # Body + +It is possible to declare the return type of a callable without specifying +the call signature by substituting a literal ellipsis +for the list of arguments in the type hint: `Callable[..., ReturnType]`. +`None` as a type hint is a special case and is replaced by `type(None)`. + +Generics +-------- + +Since type information about objects kept in containers cannot be statically +inferred in a generic way, abstract base classes have been extended to support +subscription to denote expected types for container elements. + +.. code-block:: python + + from typing import Mapping, Sequence + + def notify_by_email(employees: Sequence[Employee], + overrides: Mapping[str, str]) -> None: ... + +Generics can be parametrized by using a new factory available in typing +called TypeVar. + +.. code-block:: python + + from typing import Sequence, TypeVar + + T = TypeVar('T') # Declare type variable + + def first(l: Sequence[T]) -> T: # Generic function + return l[0] + + +User-defined generic types +-------------------------- + +A user-defined class can be defined as a generic class. + +.. code-block:: python + + from typing import TypeVar, Generic + from logging import Logger + + T = TypeVar('T') + + class LoggedVar(Generic[T]): + def __init__(self, value: T, name: str, logger: Logger) -> None: + self.name = name + self.logger = logger + self.value = value + + def set(self, new: T) -> None: + self.log('Set ' + repr(self.value)) + self.value = new + + def get(self) -> T: + self.log('Get ' + repr(self.value)) + return self.value + + def log(self, message: str) -> None: + self.logger.info('{}: {}'.format(self.name, message)) + +`Generic[T]` as a base class defines that the class `LoggedVar` takes a single +type parameter `T` . This also makes `T` valid as a type within the class body. + +The `Generic` base class uses a metaclass that defines `__getitem__` so that +`LoggedVar[t]` is valid as a type:: + + from typing import Iterable + + def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: + for var in vars: + var.set(0) + +A generic type can have any number of type variables, and type variables may +be constrained:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + S = TypeVar('S', int, str) + + class StrangePair(Generic[T, S]): + ... + +Each type variable argument to `Generic` must be distinct. +This is thus invalid:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + + class Pair(Generic[T, T]): # INVALID + ... + +You can use multiple inheritance with `Generic`:: + + from typing import TypeVar, Generic, Sized + + T = TypeVar('T') + + class LinkedList(Sized, Generic[T]): + ... + +Subclassing a generic class without specifying type parameters assumes `Any` +for each position. In the following example, `MyIterable` is not generic but +implicitly inherits from `Iterable[Any]`:: + + from typing import Iterable + + class MyIterable(Iterable): # Same as Iterable[Any] + +Generic metaclasses are not supported. + +The `Any` type +-------------- + +A special kind of type is `Any`. Every type is a subtype of `Any`. +This is also true for the builtin type object. However, to the static type +checker these are completely different. + +When the type of a value is `object`, the type checker will reject almost all +operations on it, and assigning it to a variable (or using it as a return value) +of a more specialized type is a type error. On the other hand, when a value has +type `Any`, the type checker will allow all operations on it, and a value of +type `Any` can be assigned to a variable (or used as a return value) of a more +constrained type. + +Default argument values +----------------------- + +Use a literal ellipsis `...` to declare an argument as having a default value:: + + from typing import AnyStr + + def foo(x: AnyStr, y: AnyStr = ...) -> AnyStr: ... + + +Classes, functions, and decorators +---------------------------------- + +The module defines the following classes, functions and decorators: + +.. class:: Any + + Special type indicating an unconstrained type. + + * Any object is an instance of `Any`. + * Any class is a subclass of `Any`. + * As a special case, `Any` and `object` are subclasses of each other. + +.. class:: TypeVar + + Type variable. + + Usage:: + + T = TypeVar('T') # Can be anything + A = TypeVar('A', str, bytes) # Must be str or bytes + + Type variables exist primarily for the benefit of static type + checkers. They serve as the parameters for generic types as well + as for generic function definitions. See class Generic for more + information on generic types. Generic functions work as follows: + + .. code-block:: python + + def repeat(x: T, n: int) -> Sequence[T]: + """Return a list containing n references to x.""" + return [x]*n + + def longest(x: A, y: A) -> A: + """Return the longest of two strings.""" + return x if len(x) >= len(y) else y + + The latter example's signature is essentially the overloading + of `(str, str) -> str` and `(bytes, bytes) -> bytes`. Also note + that if the arguments are instances of some subclass of `str`, + the return type is still plain `str`. + + At runtime, `isinstance(x, T)` will raise `TypeError`. In general, + `isinstance` and `issublass` should not be used with types. + + Type variables may be marked covariant or contravariant by passing + `covariant=True` or `contravariant=True`. See :pep:`484` for more + details. By default type variables are invariant. + +.. class:: Union + + Union type; `Union[X, Y]` means either X or Y. + + To define a union, use e.g. `Union[int, str]`. Details: + + * The arguments must be types and there must be at least one. + + * Unions of unions are flattened, e.g.:: + + Union[Union[int, str], float] == Union[int, str, float] + + * Unions of a single argument vanish, e.g.:: + + Union[int] == int # The constructor actually returns int + + * Redundant arguments are skipped, e.g.:: + + Union[int, str, int] == Union[int, str] + + * When comparing unions, the argument order is ignored, e.g.:: + + Union[int, str] == Union[str, int] + + * If `Any` is present it is the sole survivor, e.g.:: + + Union[int, Any] == Any + + * You cannot subclass or instantiate a union. + + * You cannot write `Union[X][Y]` + + * You can use `Optional[X]` as a shorthand for `Union[X, None]`. + +.. class:: Optional + + Optional type. + + `Optional[X]` is equivalent to `Union[X, type(None)]`. + +.. class:: Tuple + + Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + with the first item of type X and the second of type Y. + + Example: `Tuple[T1, T2]` is a tuple of two elements corresponding + to type variables T1 and T2. `Tuple[int, float, str]` is a tuple + of an int, a float and a string. + + To specify a variable-length tuple of homogeneous type, + use literal ellipsis, e.g. `Tuple[int, ...]`. + +.. class:: Callable + + Callable type; `Callable[[int], str]` is a function of (int) -> str. + + The subscription syntax must always be used with exactly two + values: the argument list and the return type. The argument list + must be a list of types; the return type must be a single type. + + There is no syntax to indicate optional or keyword arguments, + such function types are rarely used as callback types. + `Callable[..., ReturnType]` could be used to type hint a callable + taking any number of arguments and returning `ReturnType`. + A plain `Callable` is equivalent to `Callable[..., Any]`. + +.. class:: Generic + + Abstract base class for generic types. + + A generic type is typically declared by inheriting from an + instantiation of this class with one or more type variables. + For example, a generic mapping type might be defined as:: + + class Mapping(Generic[KT, VT]): + def __getitem__(self, key: KT) -> VT: + ... + # Etc. + + This class can then be used as follows:: + + X = TypeVar('X') + Y = TypeVar('Y') + def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: + try: + return mapping[key] + except KeyError: + return default + +.. class:: Iterable(Generic[T_co]) + +.. class:: Iterator(Iterable[T_co]) + +.. class:: SupportsInt + +.. class:: SupportsFloat + +.. class:: SupportsAbs + +.. class:: SupportsRound + +.. class:: Reversible + +.. class:: Container(Generic[T_co]) + +.. class:: AbstractSet(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSet(AbstractSet[T]) + +.. class:: Mapping(Sized, Iterable[KT_co], Container[KT_co], Generic[KT_co, VT_co]) + +.. class:: MutableMapping(Mapping[KT, VT]) + +.. class:: Sequence(Sized, Iterable[T_co], Container[T_co]) + +.. class:: MutableSequence(Sequence[T]) + +.. class:: ByteString(Sequence[int]) + +.. class:: List(list, MutableSequence[T]) + +.. class:: Set(set, MutableSet[T]) + +.. class:: MappingView(Sized, Iterable[T_co]) + +.. class:: KeysView(MappingView[KT_co], AbstractSet[KT_co]) + +.. class:: ItemsView(MappingView, Generic[KT_co, VT_co]) + +.. class:: ValuesView(MappingView[VT_co]) + +.. class:: Dict(dict, MutableMapping[KT, VT]) + +.. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]) + +.. class:: io + + Wrapper namespace for IO generic classes. + +.. class:: re + + Wrapper namespace for re type classes. + +.. function:: NamedTuple(typename, fields) + + Typed version of namedtuple. + + Usage:: + + Employee = typing.NamedTuple('Employee', [('name', str), 'id', int)]) + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has one extra attribute: _field_types, + giving a dict mapping field names to types. (The field names + are in the _fields attribute, which is part of the namedtuple + API.) + +.. function:: cast(typ, val) + + Cast a value to a type. + + This returns the value unchanged. To the type checker this + signals that the return value has the designated type, but at + runtime we intentionally don't check anything (we want this + to be as fast as possible). + +.. function:: get_type_hints(obj) + + Return type hints for a function or method object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, and if necessary + adds Optional[t] if a default value equal to None is set. + +.. decorator:: no_type_check(arg) + + Decorator to indicate that annotations are not type hints. + + The argument must be a class or function; if it is a class, it + applies recursively to all methods defined in that class (but not + to methods defined in its superclasses or subclasses). + + This mutates the function(s) in place. + +.. decorator:: no_type_check_decorator(decorator) + + Decorator to give another decorator the @no_type_check effect. + + This wraps the decorator with something that wraps the decorated + function in @no_type_check. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 12:27:39 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 05 Aug 2015 10:27:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzOTcz?= =?utf-8?q?=3A_Update_typing=2Epy_from_GitHub_repo=2E?= Message-ID: <20150805102738.53973.49986@psf.io> https://hg.python.org/cpython/rev/f142b7c7a8e3 changeset: 97266:f142b7c7a8e3 branch: 3.5 parent: 97262:565148a084b1 user: Guido van Rossum date: Wed Aug 05 12:11:06 2015 +0200 summary: Issue #23973: Update typing.py from GitHub repo. files: Lib/test/test_typing.py | 275 +++++++-------------------- Lib/typing.py | 223 +++++++-------------- Misc/NEWS | 2 + 3 files changed, 152 insertions(+), 348 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -41,11 +41,9 @@ class AnyTests(TestCase): - def test_any_instance(self): - self.assertIsInstance(Employee(), Any) - self.assertIsInstance(42, Any) - self.assertIsInstance(None, Any) - self.assertIsInstance(object(), Any) + def test_any_instance_type_error(self): + with self.assertRaises(TypeError): + isinstance(42, Any) def test_any_subclass(self): self.assertTrue(issubclass(Employee, Any)) @@ -109,9 +107,6 @@ def test_basic_plain(self): T = TypeVar('T') - # Nothing is an instance if T. - with self.assertRaises(TypeError): - isinstance('', T) # Every class is a subclass of T. assert issubclass(int, T) assert issubclass(str, T) @@ -119,12 +114,16 @@ assert T == T # T is a subclass of itself. assert issubclass(T, T) + # T is an instance of TypeVar + assert isinstance(T, TypeVar) + + def test_typevar_instance_type_error(self): + T = TypeVar('T') + with self.assertRaises(TypeError): + isinstance(42, T) def test_basic_constrained(self): A = TypeVar('A', str, bytes) - # Nothing is an instance of A. - with self.assertRaises(TypeError): - isinstance('', A) # Only str and bytes are subclasses of A. assert issubclass(str, A) assert issubclass(bytes, A) @@ -213,8 +212,6 @@ def test_basics(self): u = Union[int, float] self.assertNotEqual(u, Union) - self.assertIsInstance(42, u) - self.assertIsInstance(3.14, u) self.assertTrue(issubclass(int, u)) self.assertTrue(issubclass(float, u)) @@ -247,7 +244,6 @@ def test_subclass(self): u = Union[int, Employee] - self.assertIsInstance(Manager(), u) self.assertTrue(issubclass(Manager, u)) def test_self_subclass(self): @@ -256,7 +252,6 @@ def test_multiple_inheritance(self): u = Union[int, Employee] - self.assertIsInstance(ManagingFounder(), u) self.assertTrue(issubclass(ManagingFounder, u)) def test_single_class_disappears(self): @@ -309,9 +304,6 @@ o = Optional[int] u = Union[int, None] self.assertEqual(o, u) - self.assertIsInstance(42, o) - self.assertIsInstance(None, o) - self.assertNotIsInstance(3.14, o) def test_empty(self): with self.assertRaises(TypeError): @@ -321,11 +313,9 @@ assert issubclass(Union[int, str], Union) assert not issubclass(int, Union) - def test_isinstance_union(self): - # Nothing is an instance of bare Union. - assert not isinstance(42, Union) - assert not isinstance(int, Union) - assert not isinstance(Union[int, str], Union) + def test_union_instance_type_error(self): + with self.assertRaises(TypeError): + isinstance(42, Union[int, str]) class TypeVarUnionTests(TestCase): @@ -352,22 +342,11 @@ TU = TypeVar('TU', Union[int, float], None) assert issubclass(int, TU) assert issubclass(float, TU) - with self.assertRaises(TypeError): - isinstance(42, TU) - with self.assertRaises(TypeError): - isinstance('', TU) class TupleTests(TestCase): def test_basics(self): - self.assertIsInstance((42, 3.14, ''), Tuple) - self.assertIsInstance((42, 3.14, ''), Tuple[int, float, str]) - self.assertIsInstance((42,), Tuple[int]) - self.assertNotIsInstance((3.14,), Tuple[int]) - self.assertNotIsInstance((42, 3.14), Tuple[int, float, str]) - self.assertNotIsInstance((42, 3.14, 100), Tuple[int, float, str]) - self.assertNotIsInstance((42, 3.14, 100), Tuple[int, float]) self.assertTrue(issubclass(Tuple[int, str], Tuple)) self.assertTrue(issubclass(Tuple[int, str], Tuple[int, str])) self.assertFalse(issubclass(int, Tuple)) @@ -382,14 +361,11 @@ pass self.assertTrue(issubclass(MyTuple, Tuple)) - def test_tuple_ellipsis(self): - t = Tuple[int, ...] - assert isinstance((), t) - assert isinstance((1,), t) - assert isinstance((1, 2), t) - assert isinstance((1, 2, 3), t) - assert not isinstance((3.14,), t) - assert not isinstance((1, 2, 3.14,), t) + def test_tuple_instance_type_error(self): + with self.assertRaises(TypeError): + isinstance((0, 0), Tuple[int, int]) + with self.assertRaises(TypeError): + isinstance((0, 0), Tuple) def test_tuple_ellipsis_subclass(self): @@ -419,18 +395,6 @@ class CallableTests(TestCase): - def test_basics(self): - c = Callable[[int, float], str] - - def flub(a: int, b: float) -> str: - return str(a * b) - - def flob(a: int, b: int) -> str: - return str(a * b) - - self.assertIsInstance(flub, c) - self.assertNotIsInstance(flob, c) - def test_self_subclass(self): self.assertTrue(issubclass(Callable[[int], int], Callable)) self.assertFalse(issubclass(Callable, Callable[[int], int])) @@ -453,91 +417,6 @@ self.assertNotEqual(Callable[[int], int], Callable[[], int]) self.assertNotEqual(Callable[[int], int], Callable) - def test_with_none(self): - c = Callable[[None], None] - - def flub(self: None) -> None: - pass - - def flab(self: Any) -> None: - pass - - def flob(self: None) -> Any: - pass - - self.assertIsInstance(flub, c) - self.assertIsInstance(flab, c) - self.assertNotIsInstance(flob, c) # Test contravariance. - - def test_with_subclasses(self): - c = Callable[[Employee, Manager], Employee] - - def flub(a: Employee, b: Employee) -> Manager: - return Manager() - - def flob(a: Manager, b: Manager) -> Employee: - return Employee() - - self.assertIsInstance(flub, c) - self.assertNotIsInstance(flob, c) - - def test_with_default_args(self): - c = Callable[[int], int] - - def flub(a: int, b: float = 3.14) -> int: - return a - - def flab(a: int, *, b: float = 3.14) -> int: - return a - - def flob(a: int = 42) -> int: - return a - - self.assertIsInstance(flub, c) - self.assertIsInstance(flab, c) - self.assertIsInstance(flob, c) - - def test_with_varargs(self): - c = Callable[[int], int] - - def flub(*args) -> int: - return 42 - - def flab(*args: int) -> int: - return 42 - - def flob(*args: float) -> int: - return 42 - - self.assertIsInstance(flub, c) - self.assertIsInstance(flab, c) - self.assertNotIsInstance(flob, c) - - def test_with_method(self): - - class C: - - def imethod(self, arg: int) -> int: - self.last_arg = arg - return arg + 1 - - @classmethod - def cmethod(cls, arg: int) -> int: - cls.last_cls_arg = arg - return arg + 1 - - @staticmethod - def smethod(arg: int) -> int: - return arg + 1 - - ct = Callable[[int], int] - self.assertIsInstance(C().imethod, ct) - self.assertIsInstance(C().cmethod, ct) - self.assertIsInstance(C.cmethod, ct) - self.assertIsInstance(C().smethod, ct) - self.assertIsInstance(C.smethod, ct) - self.assertIsInstance(C.imethod, Callable[[Any, int], int]) - def test_cannot_subclass(self): with self.assertRaises(TypeError): @@ -556,21 +435,21 @@ with self.assertRaises(TypeError): c() - def test_varargs(self): - ct = Callable[..., int] + def test_callable_instance_works(self): + f = lambda: None + assert isinstance(f, Callable) + assert not isinstance(None, Callable) - def foo(a, b) -> int: - return 42 - - def bar(a=42) -> int: - return a - - def baz(*, x, y, z) -> int: - return 100 - - self.assertIsInstance(foo, ct) - self.assertIsInstance(bar, ct) - self.assertIsInstance(baz, ct) + def test_callable_instance_type_error(self): + f = lambda: None + with self.assertRaises(TypeError): + assert isinstance(f, Callable[[], None]) + with self.assertRaises(TypeError): + assert isinstance(f, Callable[[], Any]) + with self.assertRaises(TypeError): + assert not isinstance(None, Callable[[], None]) + with self.assertRaises(TypeError): + assert not isinstance(None, Callable[[], Any]) def test_repr(self): ct0 = Callable[[], bool] @@ -580,6 +459,14 @@ ctv = Callable[..., str] self.assertEqual(repr(ctv), 'typing.Callable[..., str]') + def test_callable_with_ellipsis(self): + + def foo(a: Callable[..., T]): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Callable[..., T]}) + XK = TypeVar('XK', str, bytes) XV = TypeVar('XV') @@ -659,6 +546,10 @@ assert issubclass(list, typing.Reversible) assert not issubclass(int, typing.Reversible) + def test_protocol_instance_type_error(self): + with self.assertRaises(TypeError): + isinstance([], typing.Reversible) + class GenericTests(TestCase): @@ -672,6 +563,14 @@ with self.assertRaises(TypeError): Y[str, bytes] + def test_init(self): + T = TypeVar('T') + S = TypeVar('S') + with self.assertRaises(TypeError): + Generic[T, T] + with self.assertRaises(TypeError): + Generic[T, S, T] + def test_repr(self): self.assertEqual(repr(SimpleMapping), __name__ + '.' + 'SimpleMapping[~XK, ~XV]') @@ -824,11 +723,11 @@ typing.Sequence[Manager]) def test_covariance_mapping(self): - # Ditto for Mapping (a generic class with two parameters). + # Ditto for Mapping (covariant in the value, invariant in the key). assert issubclass(typing.Mapping[Employee, Manager], typing.Mapping[Employee, Employee]) - assert issubclass(typing.Mapping[Manager, Employee], - typing.Mapping[Employee, Employee]) + assert not issubclass(typing.Mapping[Manager, Employee], + typing.Mapping[Employee, Employee]) assert not issubclass(typing.Mapping[Employee, Manager], typing.Mapping[Manager, Manager]) assert not issubclass(typing.Mapping[Manager, Employee], @@ -889,6 +788,11 @@ right_hints = get_type_hints(t.add_right, globals(), locals()) assert right_hints['node'] == Optional[Node[T]] + def test_forwardref_instance_type_error(self): + fr = typing._ForwardRef('int') + with self.assertRaises(TypeError): + isinstance(42, fr) + def test_union_forward(self): def foo(a: Union['T']): @@ -913,6 +817,14 @@ self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': Callable[[T], T]}) + def test_callable_with_ellipsis_forward(self): + + def foo(a: 'Callable[..., T]'): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': Callable[..., T]}) + def test_syntax_error(self): with self.assertRaises(SyntaxError): @@ -1069,50 +981,17 @@ def test_list(self): assert issubclass(list, typing.List) - assert isinstance([], typing.List) - assert not isinstance((), typing.List) - t = typing.List[int] - assert isinstance([], t) - assert isinstance([42], t) - assert not isinstance([''], t) def test_set(self): assert issubclass(set, typing.Set) assert not issubclass(frozenset, typing.Set) - assert isinstance(set(), typing.Set) - assert not isinstance({}, typing.Set) - t = typing.Set[int] - assert isinstance(set(), t) - assert isinstance({42}, t) - assert not isinstance({''}, t) def test_frozenset(self): assert issubclass(frozenset, typing.FrozenSet) assert not issubclass(set, typing.FrozenSet) - assert isinstance(frozenset(), typing.FrozenSet) - assert not isinstance({}, typing.FrozenSet) - t = typing.FrozenSet[int] - assert isinstance(frozenset(), t) - assert isinstance(frozenset({42}), t) - assert not isinstance(frozenset({''}), t) - assert not isinstance({42}, t) - - def test_mapping_views(self): - # TODO: These tests are kind of lame. - assert isinstance({}.keys(), typing.KeysView) - assert isinstance({}.items(), typing.ItemsView) - assert isinstance({}.values(), typing.ValuesView) def test_dict(self): assert issubclass(dict, typing.Dict) - assert isinstance({}, typing.Dict) - assert not isinstance([], typing.Dict) - t = typing.Dict[int, str] - assert isinstance({}, t) - assert isinstance({42: ''}, t) - assert not isinstance({42: 42}, t) - assert not isinstance({'': 42}, t) - assert not isinstance({'': ''}, t) def test_no_list_instantiation(self): with self.assertRaises(TypeError): @@ -1191,8 +1070,6 @@ yield 42 g = foo() assert issubclass(type(g), typing.Generator) - assert isinstance(g, typing.Generator) - assert not isinstance(foo, typing.Generator) assert issubclass(typing.Generator[Manager, Employee, Manager], typing.Generator[Employee, Manager, Employee]) assert not issubclass(typing.Generator[Manager, Manager, Manager], @@ -1228,12 +1105,6 @@ assert len(MMB[str, str]()) == 0 assert len(MMB[KT, VT]()) == 0 - def test_recursive_dict(self): - D = typing.Dict[int, 'D'] # Uses a _ForwardRef - assert isinstance({}, D) # Easy - assert isinstance({0: {}}, D) # Touches _ForwardRef - assert isinstance({0: {0: {}}}, D) # Etc... - class NamedTupleTests(TestCase): @@ -1294,8 +1165,6 @@ def test_basics(self): pat = re.compile('[a-z]+', re.I) assert issubclass(pat.__class__, Pattern) - assert isinstance(pat, Pattern[str]) - assert not isinstance(pat, Pattern[bytes]) assert issubclass(type(pat), Pattern) assert issubclass(type(pat), Pattern[str]) @@ -1307,12 +1176,10 @@ assert issubclass(type(mat), Match[str]) p = Pattern[Union[str, bytes]] - assert isinstance(pat, p) assert issubclass(Pattern[str], Pattern) assert issubclass(Pattern[str], p) m = Match[Union[bytes, str]] - assert isinstance(mat, m) assert issubclass(Match[bytes], Match) assert issubclass(Match[bytes], m) @@ -1327,6 +1194,12 @@ with self.assertRaises(TypeError): # Too complicated? m[str] + with self.assertRaises(TypeError): + # We don't support isinstance(). + isinstance(42, Pattern) + with self.assertRaises(TypeError): + # We don't support isinstance(). + isinstance(42, Pattern[str]) def test_repr(self): assert repr(Pattern) == 'Pattern[~AnyStr]' diff --git a/Lib/typing.py b/Lib/typing.py --- a/Lib/typing.py +++ b/Lib/typing.py @@ -128,6 +128,8 @@ class Final: """Mix-in class to prevent instantiation.""" + __slots__ = () + def __new__(self, *args, **kwds): raise TypeError("Cannot instantiate %r" % self.__class__) @@ -176,6 +178,9 @@ self.__forward_evaluated__ = True return self.__forward_value__ + def __instancecheck__(self, obj): + raise TypeError("Forward references cannot be used with isinstance().") + def __subclasscheck__(self, cls): if not self.__forward_evaluated__: globalns = self.__forward_frame__.f_globals @@ -186,16 +191,6 @@ return False # Too early. return issubclass(cls, self.__forward_value__) - def __instancecheck__(self, obj): - if not self.__forward_evaluated__: - globalns = self.__forward_frame__.f_globals - localns = self.__forward_frame__.f_locals - try: - self._eval_type(globalns, localns) - except NameError: - return False # Too early. - return isinstance(obj, self.__forward_value__) - def __repr__(self): return '_ForwardRef(%r)' % (self.__forward_arg__,) @@ -211,6 +206,8 @@ False. """ + __slots__ = ('name', 'type_var', 'impl_type', 'type_checker') + def __new__(cls, *args, **kwds): """Constructor. @@ -259,8 +256,7 @@ self.impl_type, self.type_checker) def __instancecheck__(self, obj): - return (isinstance(obj, self.impl_type) and - isinstance(self.type_checker(obj), self.type_var)) + raise TypeError("Type aliases cannot be used with isinstance().") def __subclasscheck__(self, cls): if cls is Any: @@ -332,8 +328,8 @@ self = super().__new__(cls, name, bases, namespace, _root=_root) return self - def __instancecheck__(self, instance): - return True + def __instancecheck__(self, obj): + raise TypeError("Any cannot be used with isinstance().") def __subclasscheck__(self, cls): if not isinstance(cls, type): @@ -349,6 +345,8 @@ - As a special case, Any and object are subclasses of each other. """ + __slots__ = () + class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): """Type variable. @@ -447,7 +445,6 @@ VT = TypeVar('VT') # Value type. T_co = TypeVar('T_co', covariant=True) # Any type covariant containers. V_co = TypeVar('V_co', covariant=True) # Any type covariant containers. -KT_co = TypeVar('KT_co', covariant=True) # Key type covariant containers. VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers. T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant. @@ -548,9 +545,8 @@ def __hash__(self): return hash(self.__union_set_params__) - def __instancecheck__(self, instance): - return (self.__union_set_params__ is not None and - any(isinstance(instance, t) for t in self.__union_params__)) + def __instancecheck__(self, obj): + raise TypeError("Unions cannot be used with isinstance().") def __subclasscheck__(self, cls): if cls is Any: @@ -645,6 +641,8 @@ Optional[X] is equivalent to Union[X, type(None)]. """ + __slots__ = () + class TupleMeta(TypingMeta): """Metaclass for Tuple.""" @@ -709,18 +707,8 @@ def __hash__(self): return hash(self.__tuple_params__) - def __instancecheck__(self, t): - if not isinstance(t, tuple): - return False - if self.__tuple_params__ is None: - return True - if self.__tuple_use_ellipsis__: - p = self.__tuple_params__[0] - return all(isinstance(x, p) for x in t) - else: - return (len(t) == len(self.__tuple_params__) and - all(isinstance(x, p) - for x, p in zip(t, self.__tuple_params__))) + def __instancecheck__(self, obj): + raise TypeError("Tuples cannot be used with isinstance().") def __subclasscheck__(self, cls): if cls is Any: @@ -754,6 +742,8 @@ To specify a variable-length tuple of homogeneous type, use Sequence[T]. """ + __slots__ = () + class CallableMeta(TypingMeta): """Metaclass for Callable.""" @@ -787,7 +777,10 @@ def _eval_type(self, globalns, localns): if self.__args__ is None and self.__result__ is None: return self - args = [_eval_type(t, globalns, localns) for t in self.__args__] + if self.__args__ is Ellipsis: + args = self.__args__ + else: + args = [_eval_type(t, globalns, localns) for t in self.__args__] result = _eval_type(self.__result__, globalns, localns) if args == self.__args__ and result == self.__result__: return self @@ -826,57 +819,14 @@ def __hash__(self): return hash(self.__args__) ^ hash(self.__result__) - def __instancecheck__(self, instance): - if not callable(instance): - return False + def __instancecheck__(self, obj): + # For unparametrized Callable we allow this, because + # typing.Callable should be equivalent to + # collections.abc.Callable. if self.__args__ is None and self.__result__ is None: - return True - assert self.__args__ is not None - assert self.__result__ is not None - my_args, my_result = self.__args__, self.__result__ - import inspect # TODO: Avoid this import. - # Would it be better to use Signature objects? - try: - (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, - annotations) = inspect.getfullargspec(instance) - except TypeError: - return False # We can't find the signature. Give up. - msg = ("When testing isinstance(, Callable[...], " - "'s annotations must be types.") - if my_args is not Ellipsis: - if kwonlyargs and (not kwonlydefaults or - len(kwonlydefaults) < len(kwonlyargs)): - return False - if isinstance(instance, types.MethodType): - # For methods, getfullargspec() includes self/cls, - # but it's not part of the call signature, so drop it. - del args[0] - min_call_args = len(args) - if defaults: - min_call_args -= len(defaults) - if varargs: - max_call_args = 999999999 - if len(args) < len(my_args): - args += [varargs] * (len(my_args) - len(args)) - else: - max_call_args = len(args) - if not min_call_args <= len(my_args) <= max_call_args: - return False - for my_arg_type, name in zip(my_args, args): - if name in annotations: - annot_type = _type_check(annotations[name], msg) - else: - annot_type = Any - if not issubclass(my_arg_type, annot_type): - return False - # TODO: If mutable type, check invariance? - if 'return' in annotations: - annot_return_type = _type_check(annotations['return'], msg) - # Note contravariance here! - if not issubclass(annot_return_type, my_result): - return False - # Can't find anything wrong... - return True + return isinstance(obj, collections_abc.Callable) + else: + raise TypeError("Callable[] cannot be used with isinstance().") def __subclasscheck__(self, cls): if cls is Any: @@ -900,6 +850,8 @@ such function types are rarely used as callback types. """ + __slots__ = () + def _gorg(a): """Return the farthest origin of a generic class.""" @@ -1010,6 +962,8 @@ if not isinstance(p, TypeVar): raise TypeError("Initial parameters must be " "type variables; got %s" % p) + if len(set(params)) != len(params): + raise TypeError("All type variables in Generic[...] must be distinct.") else: if len(params) != len(self.__parameters__): raise TypeError("Cannot change parameter count from %d to %d" % @@ -1073,13 +1027,6 @@ return False return issubclass(cls, self.__extra__) - def __instancecheck__(self, obj): - if super().__instancecheck__(obj): - return True - if self.__extra__ is None: - return False - return isinstance(obj, self.__extra__) - class Generic(metaclass=GenericMeta): """Abstract base class for generic types. @@ -1109,6 +1056,8 @@ # Same body as above. """ + __slots__ = () + def __new__(cls, *args, **kwds): next_in_mro = object # Look for the last occurrence of Generic or Generic[...]. @@ -1234,6 +1183,9 @@ from Generic. """ + def __instancecheck__(self, obj): + raise TypeError("Protocols cannot be used with isinstance().") + def __subclasscheck__(self, cls): if not self._is_protocol: # No structural checks since this isn't a protocol. @@ -1272,6 +1224,7 @@ attr != '__abstractmethods__' and attr != '_is_protocol' and attr != '__dict__' and + attr != '__slots__' and attr != '_get_protocol_attrs' and attr != '__parameters__' and attr != '__origin__' and @@ -1289,6 +1242,8 @@ such as Hashable). """ + __slots__ = () + _is_protocol = True @@ -1299,14 +1254,15 @@ class Iterable(Generic[T_co], extra=collections_abc.Iterable): - pass + __slots__ = () class Iterator(Iterable[T_co], extra=collections_abc.Iterator): - pass + __slots__ = () class SupportsInt(_Protocol): + __slots__ = () @abstractmethod def __int__(self) -> int: @@ -1314,6 +1270,7 @@ class SupportsFloat(_Protocol): + __slots__ = () @abstractmethod def __float__(self) -> float: @@ -1321,6 +1278,7 @@ class SupportsComplex(_Protocol): + __slots__ = () @abstractmethod def __complex__(self) -> complex: @@ -1328,30 +1286,34 @@ class SupportsBytes(_Protocol): + __slots__ = () @abstractmethod def __bytes__(self) -> bytes: pass -class SupportsAbs(_Protocol[T]): +class SupportsAbs(_Protocol[T_co]): + __slots__ = () @abstractmethod - def __abs__(self) -> T: + def __abs__(self) -> T_co: pass -class SupportsRound(_Protocol[T]): +class SupportsRound(_Protocol[T_co]): + __slots__ = () @abstractmethod - def __round__(self, ndigits: int = 0) -> T: + def __round__(self, ndigits: int = 0) -> T_co: pass -class Reversible(_Protocol[T]): +class Reversible(_Protocol[T_co]): + __slots__ = () @abstractmethod - def __reversed__(self) -> 'Iterator[T]': + def __reversed__(self) -> 'Iterator[T_co]': pass @@ -1359,7 +1321,7 @@ class Container(Generic[T_co], extra=collections_abc.Container): - pass + __slots__ = () # Callable was defined earlier. @@ -1374,7 +1336,8 @@ pass -class Mapping(Sized, Iterable[KT_co], Container[KT_co], Generic[KT_co, VT_co], +# NOTE: Only the value type is covariant. +class Mapping(Sized, Iterable[KT], Container[KT], Generic[VT_co], extra=collections_abc.Mapping): pass @@ -1399,19 +1362,7 @@ ByteString.register(type(memoryview(b''))) -class _ListMeta(GenericMeta): - - def __instancecheck__(self, obj): - if not super().__instancecheck__(obj): - return False - itemtype = self.__parameters__[0] - for x in obj: - if not isinstance(x, itemtype): - return False - return True - - -class List(list, MutableSequence[T], metaclass=_ListMeta): +class List(list, MutableSequence[T]): def __new__(cls, *args, **kwds): if _geqv(cls, List): @@ -1420,19 +1371,7 @@ return list.__new__(cls, *args, **kwds) -class _SetMeta(GenericMeta): - - def __instancecheck__(self, obj): - if not super().__instancecheck__(obj): - return False - itemtype = self.__parameters__[0] - for x in obj: - if not isinstance(x, itemtype): - return False - return True - - -class Set(set, MutableSet[T], metaclass=_SetMeta): +class Set(set, MutableSet[T]): def __new__(cls, *args, **kwds): if _geqv(cls, Set): @@ -1441,7 +1380,7 @@ return set.__new__(cls, *args, **kwds) -class _FrozenSetMeta(_SetMeta): +class _FrozenSetMeta(GenericMeta): """This metaclass ensures set is not a subclass of FrozenSet. Without this metaclass, set would be considered a subclass of @@ -1454,13 +1393,9 @@ return False return super().__subclasscheck__(cls) - def __instancecheck__(self, obj): - if issubclass(obj.__class__, Set): - return False - return super().__instancecheck__(obj) - class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta): + __slots__ = () def __new__(cls, *args, **kwds): if _geqv(cls, FrozenSet): @@ -1473,13 +1408,13 @@ pass -class KeysView(MappingView[KT_co], AbstractSet[KT_co], +class KeysView(MappingView[KT], AbstractSet[KT], extra=collections_abc.KeysView): pass -# TODO: Enable Set[Tuple[KT_co, VT_co]] instead of Generic[KT_co, VT_co]. -class ItemsView(MappingView, Generic[KT_co, VT_co], +# TODO: Enable Set[Tuple[KT, VT_co]] instead of Generic[KT, VT_co]. +class ItemsView(MappingView, Generic[KT, VT_co], extra=collections_abc.ItemsView): pass @@ -1488,20 +1423,7 @@ pass -class _DictMeta(GenericMeta): - - def __instancecheck__(self, obj): - if not super().__instancecheck__(obj): - return False - keytype, valuetype = self.__parameters__ - for key, value in obj.items(): - if not (isinstance(key, keytype) and - isinstance(value, valuetype)): - return False - return True - - -class Dict(dict, MutableMapping[KT, VT], metaclass=_DictMeta): +class Dict(dict, MutableMapping[KT, VT]): def __new__(cls, *args, **kwds): if _geqv(cls, Dict): @@ -1521,6 +1443,7 @@ class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co], extra=_G_base): + __slots__ = () def __new__(cls, *args, **kwds): if _geqv(cls, Generator): @@ -1564,6 +1487,8 @@ way to track the other distinctions in the type system. """ + __slots__ = () + @abstractproperty def mode(self) -> str: pass @@ -1648,6 +1573,8 @@ class BinaryIO(IO[bytes]): """Typed version of the return of open() in binary mode.""" + __slots__ = () + @abstractmethod def write(self, s: Union[bytes, bytearray]) -> int: pass @@ -1660,6 +1587,8 @@ class TextIO(IO[str]): """Typed version of the return of open() in text mode.""" + __slots__ = () + @abstractproperty def buffer(self) -> BinaryIO: pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #23973: Update typing.py from GitHub repo. + - Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. - Issue #23652: Make it possible to compile the select module against the -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 15:25:28 2015 From: python-checkins at python.org (nick.coghlan) Date: Wed, 05 Aug 2015 13:25:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_issue_=2324129_from_3=2E4?= Message-ID: <20150805132528.23388.21060@psf.io> https://hg.python.org/cpython/rev/5e4d21311772 changeset: 97273:5e4d21311772 branch: 3.5 parent: 97270:f0cdbc5d2cf3 parent: 97272:94e215a5e24b user: Nick Coghlan date: Wed Aug 05 23:23:24 2015 +1000 summary: Merge issue #24129 from 3.4 files: Doc/reference/executionmodel.rst | 173 +++++++++++------- Misc/ACKS | 1 + Misc/NEWS | 5 + 3 files changed, 112 insertions(+), 67 deletions(-) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -5,29 +5,18 @@ Execution model *************** -.. index:: single: execution model +.. index:: + single: execution model + pair: code; block +.. _prog_structure: -.. _naming: - -Naming and binding -================== - -.. index:: - pair: code; block - single: namespace - single: scope - -.. index:: - single: name - pair: binding; name - -:dfn:`Names` refer to objects. Names are introduced by name binding operations. -Each occurrence of a name in the program text refers to the :dfn:`binding` of -that name established in the innermost function block containing the use. +Structure of a programm +======================= .. index:: block +A Python program is constructed from code blocks. A :dfn:`block` is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class definition. Each command typed interactively is a block. A script file (a file given as @@ -43,43 +32,25 @@ administrative information (used for debugging) and determines where and how execution continues after the code block's execution has completed. -.. index:: scope +.. _naming: -A :dfn:`scope` defines the visibility of a name within a block. If a local -variable is defined in a block, its scope includes that block. If the -definition occurs in a function block, the scope extends to any blocks contained -within the defining one, unless a contained block introduces a different binding -for the name. The scope of names defined in a class block is limited to the -class block; it does not extend to the code blocks of methods -- this includes -comprehensions and generator expressions since they are implemented using a -function scope. This means that the following will fail:: - - class A: - a = 42 - b = list(a + i for i in range(10)) - -.. index:: single: environment - -When a name is used in a code block, it is resolved using the nearest enclosing -scope. The set of all such scopes visible to a code block is called the block's -:dfn:`environment`. - -.. index:: pair: free; variable - -If a name is bound in a block, it is a local variable of that block, unless -declared as :keyword:`nonlocal`. If a name is bound at the module level, it is -a global variable. (The variables of the module code block are local and -global.) If a variable is used in a code block but not defined there, it is a -:dfn:`free variable`. +Naming and binding +================== .. index:: - single: NameError (built-in exception) - single: UnboundLocalError + single: namespace + single: scope -When a name is not found at all, a :exc:`NameError` exception is raised. If the -name refers to a local variable that has not been bound, an -:exc:`UnboundLocalError` exception is raised. :exc:`UnboundLocalError` is a -subclass of :exc:`NameError`. +.. _bind_names: + +Binding of names +---------------- + +.. index:: + single: name + pair: binding; name + +:dfn:`Names` refer to objects. Names are introduced by name binding operations. .. index:: statement: from @@ -99,6 +70,46 @@ Each assignment or import statement occurs within a block defined by a class or function definition or at the module level (the top-level code block). +.. index:: pair: free; variable + +If a name is bound in a block, it is a local variable of that block, unless +declared as :keyword:`nonlocal` or :keyword:`global`. If a name is bound at +the module level, it is a global variable. (The variables of the module code +block are local and global.) If a variable is used in a code block but not +defined there, it is a :dfn:`free variable`. + +Each occurrence of a name in the program text refers to the :dfn:`binding` of +that name established by the following name resolution rules. + +.. _resolve_names: + +Resolution of names +------------------- + +.. index:: scope + +A :dfn:`scope` defines the visibility of a name within a block. If a local +variable is defined in a block, its scope includes that block. If the +definition occurs in a function block, the scope extends to any blocks contained +within the defining one, unless a contained block introduces a different binding +for the name. + +.. index:: single: environment + +When a name is used in a code block, it is resolved using the nearest enclosing +scope. The set of all such scopes visible to a code block is called the block's +:dfn:`environment`. + +.. index:: + single: NameError (built-in exception) + single: UnboundLocalError + +When a name is not found at all, a :exc:`NameError` exception is raised. +If the current scope is a function scope, and the name refers to a local +variable that has not yet been bound to a value at the point where the name is +used, an :exc:`UnboundLocalError` exception is raised. +:exc:`UnboundLocalError` is a subclass of :exc:`NameError`. + If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule @@ -115,7 +126,41 @@ builtins namespace is searched. The :keyword:`global` statement must precede all uses of the name. -.. XXX document "nonlocal" semantics here +The :keyword:`global` statement has the same scope as a name binding operation +in the same block. If the nearest enclosing scope for a free variable contains +a global statement, the free variable is treated as a global. + +.. XXX say more about "nonlocal" semantics here + +The :keyword:`nonlocal` statement causes corresponding names to refer +to previously bound variables in the nearest enclosing function scope. +:exc:`SyntaxError` is raised at compile time if the given name does not +exist in any enclosing function scope. + +.. index:: module: __main__ + +The namespace for a module is automatically created the first time a module is +imported. The main module for a script is always called :mod:`__main__`. + +Class definition blocks and arguments to :func:`exec` and :func:`eval` are +special in the context of name resolution. +A class definition is an executable statement that may use and define names. +These references follow the normal rules for name resolution with an exception +that unbound local variables are looked up in the global namespace. +The namespace of the class definition becomes the attribute dictionary of +the class. The scope of names defined in a class block is limited to the +class block; it does not extend to the code blocks of methods -- this includes +comprehensions and generator expressions since they are implemented using a +function scope. This means that the following will fail:: + + class A: + a = 42 + b = list(a + i for i in range(10)) + +.. _restrict_exec: + +Builtins and restricted execution +--------------------------------- .. index:: pair: restricted; execution @@ -135,26 +180,20 @@ :keyword:`import` the :mod:`builtins` module and modify its attributes appropriately. -.. index:: module: __main__ - -The namespace for a module is automatically created the first time a module is -imported. The main module for a script is always called :mod:`__main__`. - -The :keyword:`global` statement has the same scope as a name binding operation -in the same block. If the nearest enclosing scope for a free variable contains -a global statement, the free variable is treated as a global. - -A class definition is an executable statement that may use and define names. -These references follow the normal rules for name resolution. The namespace of -the class definition becomes the attribute dictionary of the class. Names -defined at the class scope are not visible in methods. - - .. _dynamic-features: Interaction with dynamic features --------------------------------- +Name resolution of free variables occurs at runtime, not at compile time. +This means that the following code will print 42:: + + i = 10 + def f(): + print(i) + i = 42 + f() + There are several cases where Python statements are illegal when used in conjunction with nested scopes that contain free variables. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -836,6 +836,7 @@ Alain Leufroy Mark Levinson Mark Levitt +Ivan Levkivskyi William Lewis Akira Li Xuanji Li diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,11 @@ Documentation ------------- +- Issue #24129: Clarify the reference documentation for name resolution. + This includes removing the assumption that readers will be familiar with the + name resolution scheme Python used prior to the introduction of lexical + scoping for function namespaces. Patch by Ivan Levkivskyi. + - Issue #20769: Improve reload() docs. Patch by Dorian Pula. - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 15:25:28 2015 From: python-checkins at python.org (nick.coghlan) Date: Wed, 05 Aug 2015 13:25:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MTI5?= =?utf-8?q?=3A_Clarify_reference_docs_for_name_resolution=2E?= Message-ID: <20150805132528.94766.93279@psf.io> https://hg.python.org/cpython/rev/94e215a5e24b changeset: 97272:94e215a5e24b branch: 3.4 parent: 97261:3c170f68407f user: Nick Coghlan date: Wed Aug 05 23:07:24 2015 +1000 summary: Issue #24129: Clarify reference docs for name resolution. This includes removing the assumption that readers will be familiar with the name resolution scheme Python used prior to the introduction of lexical scoping for function namespaces. Patch by Ivan Levkivskyi. files: Doc/reference/executionmodel.rst | 173 +++++++++++------- Misc/ACKS | 1 + Misc/NEWS | 5 + 3 files changed, 112 insertions(+), 67 deletions(-) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -5,29 +5,18 @@ Execution model *************** -.. index:: single: execution model +.. index:: + single: execution model + pair: code; block +.. _prog_structure: -.. _naming: - -Naming and binding -================== - -.. index:: - pair: code; block - single: namespace - single: scope - -.. index:: - single: name - pair: binding; name - -:dfn:`Names` refer to objects. Names are introduced by name binding operations. -Each occurrence of a name in the program text refers to the :dfn:`binding` of -that name established in the innermost function block containing the use. +Structure of a programm +======================= .. index:: block +A Python program is constructed from code blocks. A :dfn:`block` is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class definition. Each command typed interactively is a block. A script file (a file given as @@ -43,43 +32,25 @@ administrative information (used for debugging) and determines where and how execution continues after the code block's execution has completed. -.. index:: scope +.. _naming: -A :dfn:`scope` defines the visibility of a name within a block. If a local -variable is defined in a block, its scope includes that block. If the -definition occurs in a function block, the scope extends to any blocks contained -within the defining one, unless a contained block introduces a different binding -for the name. The scope of names defined in a class block is limited to the -class block; it does not extend to the code blocks of methods -- this includes -comprehensions and generator expressions since they are implemented using a -function scope. This means that the following will fail:: - - class A: - a = 42 - b = list(a + i for i in range(10)) - -.. index:: single: environment - -When a name is used in a code block, it is resolved using the nearest enclosing -scope. The set of all such scopes visible to a code block is called the block's -:dfn:`environment`. - -.. index:: pair: free; variable - -If a name is bound in a block, it is a local variable of that block, unless -declared as :keyword:`nonlocal`. If a name is bound at the module level, it is -a global variable. (The variables of the module code block are local and -global.) If a variable is used in a code block but not defined there, it is a -:dfn:`free variable`. +Naming and binding +================== .. index:: - single: NameError (built-in exception) - single: UnboundLocalError + single: namespace + single: scope -When a name is not found at all, a :exc:`NameError` exception is raised. If the -name refers to a local variable that has not been bound, an -:exc:`UnboundLocalError` exception is raised. :exc:`UnboundLocalError` is a -subclass of :exc:`NameError`. +.. _bind_names: + +Binding of names +---------------- + +.. index:: + single: name + pair: binding; name + +:dfn:`Names` refer to objects. Names are introduced by name binding operations. .. index:: statement: from @@ -99,6 +70,46 @@ Each assignment or import statement occurs within a block defined by a class or function definition or at the module level (the top-level code block). +.. index:: pair: free; variable + +If a name is bound in a block, it is a local variable of that block, unless +declared as :keyword:`nonlocal` or :keyword:`global`. If a name is bound at +the module level, it is a global variable. (The variables of the module code +block are local and global.) If a variable is used in a code block but not +defined there, it is a :dfn:`free variable`. + +Each occurrence of a name in the program text refers to the :dfn:`binding` of +that name established by the following name resolution rules. + +.. _resolve_names: + +Resolution of names +------------------- + +.. index:: scope + +A :dfn:`scope` defines the visibility of a name within a block. If a local +variable is defined in a block, its scope includes that block. If the +definition occurs in a function block, the scope extends to any blocks contained +within the defining one, unless a contained block introduces a different binding +for the name. + +.. index:: single: environment + +When a name is used in a code block, it is resolved using the nearest enclosing +scope. The set of all such scopes visible to a code block is called the block's +:dfn:`environment`. + +.. index:: + single: NameError (built-in exception) + single: UnboundLocalError + +When a name is not found at all, a :exc:`NameError` exception is raised. +If the current scope is a function scope, and the name refers to a local +variable that has not yet been bound to a value at the point where the name is +used, an :exc:`UnboundLocalError` exception is raised. +:exc:`UnboundLocalError` is a subclass of :exc:`NameError`. + If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule @@ -115,7 +126,41 @@ builtins namespace is searched. The :keyword:`global` statement must precede all uses of the name. -.. XXX document "nonlocal" semantics here +The :keyword:`global` statement has the same scope as a name binding operation +in the same block. If the nearest enclosing scope for a free variable contains +a global statement, the free variable is treated as a global. + +.. XXX say more about "nonlocal" semantics here + +The :keyword:`nonlocal` statement causes corresponding names to refer +to previously bound variables in the nearest enclosing function scope. +:exc:`SyntaxError` is raised at compile time if the given name does not +exist in any enclosing function scope. + +.. index:: module: __main__ + +The namespace for a module is automatically created the first time a module is +imported. The main module for a script is always called :mod:`__main__`. + +Class definition blocks and arguments to :func:`exec` and :func:`eval` are +special in the context of name resolution. +A class definition is an executable statement that may use and define names. +These references follow the normal rules for name resolution with an exception +that unbound local variables are looked up in the global namespace. +The namespace of the class definition becomes the attribute dictionary of +the class. The scope of names defined in a class block is limited to the +class block; it does not extend to the code blocks of methods -- this includes +comprehensions and generator expressions since they are implemented using a +function scope. This means that the following will fail:: + + class A: + a = 42 + b = list(a + i for i in range(10)) + +.. _restrict_exec: + +Builtins and restricted execution +--------------------------------- .. index:: pair: restricted; execution @@ -135,26 +180,20 @@ :keyword:`import` the :mod:`builtins` module and modify its attributes appropriately. -.. index:: module: __main__ - -The namespace for a module is automatically created the first time a module is -imported. The main module for a script is always called :mod:`__main__`. - -The :keyword:`global` statement has the same scope as a name binding operation -in the same block. If the nearest enclosing scope for a free variable contains -a global statement, the free variable is treated as a global. - -A class definition is an executable statement that may use and define names. -These references follow the normal rules for name resolution. The namespace of -the class definition becomes the attribute dictionary of the class. Names -defined at the class scope are not visible in methods. - - .. _dynamic-features: Interaction with dynamic features --------------------------------- +Name resolution of free variables occurs at runtime, not at compile time. +This means that the following code will print 42:: + + i = 10 + def f(): + print(i) + i = 42 + f() + There are several cases where Python statements are illegal when used in conjunction with nested scopes that contain free variables. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -813,6 +813,7 @@ Alain Leufroy Mark Levinson Mark Levitt +Ivan Levkivskyi William Lewis Akira Li Xuanji Li diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -412,6 +412,11 @@ Documentation ------------- +- Issue #24129: Clarify the reference documentation for name resolution. + This includes removing the assumption that readers will be familiar with the + name resolution scheme Python used prior to the introduction of lexical + scoping for function namespaces. Patch by Ivan Levkivskyi. + - Issue #20769: Improve reload() docs. Patch by Dorian Pula. - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 15:25:29 2015 From: python-checkins at python.org (nick.coghlan) Date: Wed, 05 Aug 2015 13:25:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=2324129_from_3=2E5?= Message-ID: <20150805132529.23392.63447@psf.io> https://hg.python.org/cpython/rev/e75881393cf2 changeset: 97274:e75881393cf2 parent: 97271:a9e6dd0fc9de parent: 97273:5e4d21311772 user: Nick Coghlan date: Wed Aug 05 23:24:55 2015 +1000 summary: Merge issue #24129 from 3.5 files: Doc/reference/executionmodel.rst | 173 +++++++++++------- Misc/ACKS | 1 + Misc/NEWS | 5 + 3 files changed, 112 insertions(+), 67 deletions(-) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -5,29 +5,18 @@ Execution model *************** -.. index:: single: execution model +.. index:: + single: execution model + pair: code; block +.. _prog_structure: -.. _naming: - -Naming and binding -================== - -.. index:: - pair: code; block - single: namespace - single: scope - -.. index:: - single: name - pair: binding; name - -:dfn:`Names` refer to objects. Names are introduced by name binding operations. -Each occurrence of a name in the program text refers to the :dfn:`binding` of -that name established in the innermost function block containing the use. +Structure of a programm +======================= .. index:: block +A Python program is constructed from code blocks. A :dfn:`block` is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class definition. Each command typed interactively is a block. A script file (a file given as @@ -43,43 +32,25 @@ administrative information (used for debugging) and determines where and how execution continues after the code block's execution has completed. -.. index:: scope +.. _naming: -A :dfn:`scope` defines the visibility of a name within a block. If a local -variable is defined in a block, its scope includes that block. If the -definition occurs in a function block, the scope extends to any blocks contained -within the defining one, unless a contained block introduces a different binding -for the name. The scope of names defined in a class block is limited to the -class block; it does not extend to the code blocks of methods -- this includes -comprehensions and generator expressions since they are implemented using a -function scope. This means that the following will fail:: - - class A: - a = 42 - b = list(a + i for i in range(10)) - -.. index:: single: environment - -When a name is used in a code block, it is resolved using the nearest enclosing -scope. The set of all such scopes visible to a code block is called the block's -:dfn:`environment`. - -.. index:: pair: free; variable - -If a name is bound in a block, it is a local variable of that block, unless -declared as :keyword:`nonlocal`. If a name is bound at the module level, it is -a global variable. (The variables of the module code block are local and -global.) If a variable is used in a code block but not defined there, it is a -:dfn:`free variable`. +Naming and binding +================== .. index:: - single: NameError (built-in exception) - single: UnboundLocalError + single: namespace + single: scope -When a name is not found at all, a :exc:`NameError` exception is raised. If the -name refers to a local variable that has not been bound, an -:exc:`UnboundLocalError` exception is raised. :exc:`UnboundLocalError` is a -subclass of :exc:`NameError`. +.. _bind_names: + +Binding of names +---------------- + +.. index:: + single: name + pair: binding; name + +:dfn:`Names` refer to objects. Names are introduced by name binding operations. .. index:: statement: from @@ -99,6 +70,46 @@ Each assignment or import statement occurs within a block defined by a class or function definition or at the module level (the top-level code block). +.. index:: pair: free; variable + +If a name is bound in a block, it is a local variable of that block, unless +declared as :keyword:`nonlocal` or :keyword:`global`. If a name is bound at +the module level, it is a global variable. (The variables of the module code +block are local and global.) If a variable is used in a code block but not +defined there, it is a :dfn:`free variable`. + +Each occurrence of a name in the program text refers to the :dfn:`binding` of +that name established by the following name resolution rules. + +.. _resolve_names: + +Resolution of names +------------------- + +.. index:: scope + +A :dfn:`scope` defines the visibility of a name within a block. If a local +variable is defined in a block, its scope includes that block. If the +definition occurs in a function block, the scope extends to any blocks contained +within the defining one, unless a contained block introduces a different binding +for the name. + +.. index:: single: environment + +When a name is used in a code block, it is resolved using the nearest enclosing +scope. The set of all such scopes visible to a code block is called the block's +:dfn:`environment`. + +.. index:: + single: NameError (built-in exception) + single: UnboundLocalError + +When a name is not found at all, a :exc:`NameError` exception is raised. +If the current scope is a function scope, and the name refers to a local +variable that has not yet been bound to a value at the point where the name is +used, an :exc:`UnboundLocalError` exception is raised. +:exc:`UnboundLocalError` is a subclass of :exc:`NameError`. + If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule @@ -115,7 +126,41 @@ builtins namespace is searched. The :keyword:`global` statement must precede all uses of the name. -.. XXX document "nonlocal" semantics here +The :keyword:`global` statement has the same scope as a name binding operation +in the same block. If the nearest enclosing scope for a free variable contains +a global statement, the free variable is treated as a global. + +.. XXX say more about "nonlocal" semantics here + +The :keyword:`nonlocal` statement causes corresponding names to refer +to previously bound variables in the nearest enclosing function scope. +:exc:`SyntaxError` is raised at compile time if the given name does not +exist in any enclosing function scope. + +.. index:: module: __main__ + +The namespace for a module is automatically created the first time a module is +imported. The main module for a script is always called :mod:`__main__`. + +Class definition blocks and arguments to :func:`exec` and :func:`eval` are +special in the context of name resolution. +A class definition is an executable statement that may use and define names. +These references follow the normal rules for name resolution with an exception +that unbound local variables are looked up in the global namespace. +The namespace of the class definition becomes the attribute dictionary of +the class. The scope of names defined in a class block is limited to the +class block; it does not extend to the code blocks of methods -- this includes +comprehensions and generator expressions since they are implemented using a +function scope. This means that the following will fail:: + + class A: + a = 42 + b = list(a + i for i in range(10)) + +.. _restrict_exec: + +Builtins and restricted execution +--------------------------------- .. index:: pair: restricted; execution @@ -135,26 +180,20 @@ :keyword:`import` the :mod:`builtins` module and modify its attributes appropriately. -.. index:: module: __main__ - -The namespace for a module is automatically created the first time a module is -imported. The main module for a script is always called :mod:`__main__`. - -The :keyword:`global` statement has the same scope as a name binding operation -in the same block. If the nearest enclosing scope for a free variable contains -a global statement, the free variable is treated as a global. - -A class definition is an executable statement that may use and define names. -These references follow the normal rules for name resolution. The namespace of -the class definition becomes the attribute dictionary of the class. Names -defined at the class scope are not visible in methods. - - .. _dynamic-features: Interaction with dynamic features --------------------------------- +Name resolution of free variables occurs at runtime, not at compile time. +This means that the following code will print 42:: + + i = 10 + def f(): + print(i) + i = 42 + f() + There are several cases where Python statements are illegal when used in conjunction with nested scopes that contain free variables. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -836,6 +836,7 @@ Alain Leufroy Mark Levinson Mark Levitt +Ivan Levkivskyi William Lewis Akira Li Xuanji Li diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,11 @@ Documentation ------------- +- Issue #24129: Clarify the reference documentation for name resolution. + This includes removing the assumption that readers will be familiar with the + name resolution scheme Python used prior to the introduction of lexical + scoping for function namespaces. Patch by Ivan Levkivskyi. + - Issue #20769: Improve reload() docs. Patch by Dorian Pula. - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 18:02:45 2015 From: python-checkins at python.org (chris.angelico) Date: Wed, 05 Aug 2015 16:02:45 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Introduce_PEP_0497_from_Ed_Sc?= =?utf-8?q?hofield?= Message-ID: <20150805160245.5525.68674@psf.io> https://hg.python.org/peps/rev/bc2cb060f261 changeset: 5921:bc2cb060f261 user: Chris Angelico date: Thu Aug 06 02:02:39 2015 +1000 summary: Introduce PEP 0497 from Ed Schofield files: pep-0497.txt | 313 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 313 insertions(+), 0 deletions(-) diff --git a/pep-0497.txt b/pep-0497.txt new file mode 100644 --- /dev/null +++ b/pep-0497.txt @@ -0,0 +1,313 @@ +PEP: 497 +Title: A standard mechanism for backward compatibility +Version: $Revision$ +Last-Modified: $Date$ +Author: Ed Schofield +Status: Draft +Type: Process +Created: 04-Aug-2015 +Content-Type: text/x-rst + + +Scope +===== + +This PEP is complementary to PEPs 5, 236, and 387, and shares similar +goals. + +This PEP explains the need for an additional compatibility mechanism +in support of PEP 5, "Guidelines for Language Evolution". PEP 236, +"Back to the __future__", introduced a mechanism for forward +compatibility in support of PEP 5 but noted that a new mechanism for +backward compatibility was outside the scope of that PEP. A related +PEP (in progress) introduces such a mechanism for backward +compatibility. + +PEP 5, "Guidelines for Language Evolution", notes that "This PEP [PEP 5] +does not replace or preclude other compatibility strategies such as +dynamic loading of backwards-compatible parsers." + + +Context +======= + +From PEP 236: "From time to time, Python makes an incompatible change +to the advertised semantics of core language constructs, or changes +their accidental (implementation-dependent) behavior in some way. +While this is never done capriciously, and is always done with the aim +of improving the language over the long term, over the short term it's +contentious and disrupting. PEP 5, Guidelines for Language Evolution, +suggests ways to ease the pain, and this PEP [236] introduces some +machinery in support of that." + +Also from PEP 236: "The purpose of future_statement is to make life +easier for people who keep current with the latest release in a timely +fashion. We don't hate you if you don't, but your problems are much +harder to solve, and somebody with those problems will need to write a +PEP addressing them. future_statement is aimed at a different +audience." + + +The current situation +===================== + +When an incompatible change to core language syntax or semantics is +being made, Python currently provides the future_statement mechanism +for providing forward compatibility until the release that enforces +the new syntax or semantics, but provides no corresponding standard +mechanism for providing backward compatibility after this release. + + +Problem +======= + +A consequence of this asymmetry is that, with respect to a breaking +change, the older (pre-breaking) version of the Python interpreter is +more capable than the newer (breaking) version; the older interpreter +can use both code designed prior to the change and newer code, whereas +the newer interpreter is only capable of using code that has been +upgraded to support the changed feature. + +As an example, consider the changes to the division operator +introduced in PEP 238 in 2001, soon after PEP 236 introduced the +future_statement mechanism. PEP 238 outlines a suite of useful +forward-compatibility mechanisms for "true division" in the Python 2.x +series but omits to include any backward-compatibility mechanisms for +after "true division" was first enforced in Python 3.0. Python versions +since 3.0 do not provide a backward compatibility mechanism such as +``from __past__ import division`` for code that expects the old +"classic division" semantics, whereas Python versions prior to 3.0 do +support both "classic division" code and also forward compatibility +with code expecting "true division". A further consequence of this is +that the "most compatible" interpreter with respect to the variety of +division-related Python code in the wild is Python 2.7, the version +before the breaking change was first enforced. + + +Backward compatibility as enabler for "downhill upgrades" +========================================================= + +In contrast to this situation, newer versions of application software +such as office suites tend to be more capable than earlier versions +with respect to their support for loading different versions of their +data file formats. The pattern is usually that the newer application +versions can transparently load data from either their newer or their +older data formats, and that the newer version defaults to saving data +in the newer format. Newer application software versions tend to be +backward-compatible by default. Forward compatibility is relatively +rare. + +This policy puts the user of the newer application software at an +advantage over the user of the older software, which is usually +incapable of loading data in the newer format. Sometimes it is +possible for a user of a newer software application version to export +data in an older version by choosing this option explicitly. In these +cases, the forward-compatibility this enables may or may not be +perfect; some features may be missing or the results may be otherwise +suboptimal. Upgrading is therefore easy, whereas downgrading is +harder. + +The emergent behaviour over many users from such a policy of new +attractive features plus backward compatibility features is that a +natural pressure builds up on each individual user to upgrade his or +her own application version, and, the more other users an individual +exchanges data files with, the more acute this pressure becomes. + + +Proposal - part 1 +================= + +This PEP makes two specific, related proposals. The first is that: + + PEP 5 be augmented with a 6th step in the section "Steps for + Introducing Backwards-Incompatible Features" to indicate that, when an + incompatible change to core language syntax or semantics is being + made, Python-dev's policy is to prefer and expect that, wherever + possible, a mechanism for backward compatibility be considered and + provided for future Python versions after the breaking change is + adopted by default, in addition to any mechanisms proposed for forward + compatibility such as new future_statements. Furthermore, PEP 387, + "Backwards Compatibility Policy" (if accepted) would be + augmented with the same 6th step. + + +Example +~~~~~~~ + +As an example of how this PEP is to be applied, if the latest revision +of the "true division" PEP (238) were proposed today, it would be +considered incomplete. PEP 238 notes the "severe backwards +compatibility issues" raised by the proposal and describes several +measures for forward compatibility in the Abstract and API Changes +sections. It also mentions some backward compatibility ideas raised on +c.l.py, including "Use ``from __past__ import division`` to use +classic division semantics in a module", but it does not put forward +any backward compatibility plan as part of the proposal. + +If this PEP is accepted, it would be expected that a proposal such as +PEP 238, because of its large-scale compatibility implications, would +also be accompanied by a backward compatibility plan that enables +users of future Python versions after the breaking change has come +into effect to re-enable the classic division behaviour easily in +their code. + + +Proposal - part 2 +================= + +The second proposal is that: + + Python provide a standard backward compatibility mechanism in + parallel to the ``__future__`` module mechanism for forward + compatibility. + +For reference, this document will refer to this as a "``__past__``" +mechanism hereon, although it need not have all the characteristics +of the ``__future__`` module and ``future_statement`` mechanism. + +The specific form and implementation of the ``__past__`` mechanism is +the subject of a separate PEP (in progress). However, this PEP +recommends that this ``__past__`` mechanism be designed to meet +similar criteria to those outlined in PEP 296 for ``__future__``. +Specifically: + +a. It should enable individual modules to specify obsolete behaviours +to re-enable from older Python versions on a module-by-module basis. + +b. It should be flexible enough for both Python 3.6+ and point +releases of earlier versions to reintroduce backward compatibility +with older Python syntax or semantics for user modules that invoke the +``__past__`` mechanism. + +c. It should be possible to run older code augmented to invoke +``__past__`` behaviours on older Python versions such as 2.x that have +no knowledge of the specific ``__past__`` features invoked, or even +that the ``__past__`` mechanism for backward-compatibility exists. + + +Counter-examples +~~~~~~~~~~~~~~~~ + +Some implementations of ``__past__`` mechanisms that would violate +these criteria are: + +a. Import hooks. These would normally fail to work on a +module-by-module basis; instead they apply recursively to all new +modules imported from within a module. + +b. A new piece of syntax or new semantics for Python 3.6 that is +incompatible with prior versions. + +c. A function added in Python 3.6 to a module in the Python standard +library that exists under the same name in prior Python versions. + + +Benefits +======== + +The benefit to Python-dev of adopting this proposal is that future +backward-incompatible changes can be less disruptive if these changes +each have a corresponding ``__past__`` feature that has been +implemented and can be invoked easily by users of future Python +versions. This can help the language to evolve more quickly and more +effectively to correct for design mistakes. + +The benefit to conservative users is obvious: they can add support for +the latest shiny compatibility-breaking Python version to their code +merely by adding a ``__past__`` incantation (perhaps a single line) to +each module, and that this can be automated. They can then upgrade +their interpreter to the latest version and gain access to the latest +shiny Python features. + +The benefit to the community is that, if ten thousand users rely on +package XYZ, and package XYZ can trivially add support for the latest +Python version, those ten thousand users can also upgrade to the +latest Python version quickly, without being held back waiting for +package XYZ to do this. + + +Questions and answers +===================== + +Q1: Does this PEP require that Python keep two possible sets of semantics +for each backward-incompatible feature forever? + +A1: Definitely not. Legacy features can still be phased out when +appropriate -- that is, when the majority of the user-base has +migrated to the newer Python version. This PEP merely proposes to +shift the emphasis of the development effort directed at compatibility +from 100% forwards to at least 50% backwards. Backwards compatibility +is the more powerful of the two concepts for allowing a user-base to +adopt the latest Python interpreter version. + +Notice that it has been a long time since most users have cared about +backwards compatibility for non-nested scopes, because most users have +moved comfortably past Python 2.1. + +Q2: But Python-dev is already overwhelmed and doesn't have the +bandwidth to implement / maintain the additional complexity! + +A2: Python-dev can ask the community of developers to step up and +maintain backward compatibility in Python for legacy language features +they care about. When the community stops caring about a particular +obsolete behaviour, Python-dev can stop caring too. + +The ``__past__`` mechanism could possibly be designed to be extensible +by the community, e.g. as a standard but "blessed" PyPI package, to +reduce the load on the core developers. + +Q3: Won't backward compatibility features lead to lots of cruft and +bloat and baggage in Python? + +A3: Not necessarily. First, proposals for new compatibility-breaking +features in Python could be evaluated partly on the simplicity and +maintainability of the implementation of their associated ``__past__`` +feature up-front. + +Second, some old features are simple to provide backward compatibility +for. Consider the "classic division" behaviour before Python 3.0. The +``python-future`` project contains a compatible implementation of +classic division in the function ``future.utils.old_div``: + +:: + + def old_div(a, b): + """ + Equivalent to ``a / b`` on Python 2 without ``from __future__ import + division``. + """ + if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral): + return a // b + else: + return a / b + + +Bundling such a function with Python 3.x versions, together with +a simple mechanism to invoke it for every appearance of ``a +/ b`` after an appropriate ``__past__`` invocation, need not be +onerous. + + +Q4: What about performance? Won't the performance of newer Python +versions suffer under the weight of legacy features? + +A4: This can be evaluated on a case-by-case basis. The major potential +concern is that the performance with the new default behaviour does +not suffer unduly because of the presence of the legacy option. The +performance under the influence of the ``__past__`` invocation is of +secondary importance. + + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Aug 5 18:46:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 16:46:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150805164643.29414.3398@psf.io> https://hg.python.org/cpython/rev/e7b36ab053bf changeset: 97276:e7b36ab053bf parent: 97274:e75881393cf2 parent: 97275:c29a1d78ed92 user: Yury Selivanov date: Wed Aug 05 12:46:40 2015 -0400 summary: Merge 3.5 files: Doc/whatsnew/3.5.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -266,7 +266,8 @@ .. seealso:: - :pep:`484` -- Type Hints + * :pep:`484` -- Type Hints + * :mod:`typing` module documentation PEP 471 - os.scandir() function -- a better and faster directory iterator -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 18:46:44 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 16:46:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogd2hhdHNuZXcvMy41?= =?utf-8?q?=3A_Mention_=27typing=27_module_docs_in_seealso_for_pep_484?= Message-ID: <20150805164643.53971.87247@psf.io> https://hg.python.org/cpython/rev/c29a1d78ed92 changeset: 97275:c29a1d78ed92 branch: 3.5 parent: 97273:5e4d21311772 user: Yury Selivanov date: Wed Aug 05 12:46:29 2015 -0400 summary: whatsnew/3.5: Mention 'typing' module docs in seealso for pep 484 files: Doc/whatsnew/3.5.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -266,7 +266,8 @@ .. seealso:: - :pep:`484` -- Type Hints + * :pep:`484` -- Type Hints + * :mod:`typing` module documentation PEP 471 - os.scandir() function -- a better and faster directory iterator -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 19:59:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 17:59:02 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODEy?= =?utf-8?q?=3A_Fix_asyncio=2EQueue=2Eget=28=29_to_avoid_loosing_items_on_c?= =?utf-8?q?ancellation=2E?= Message-ID: <20150805175901.41837.69496@psf.io> https://hg.python.org/cpython/rev/7aa2d3e1c885 changeset: 97277:7aa2d3e1c885 branch: 3.4 parent: 97272:94e215a5e24b user: Yury Selivanov date: Wed Aug 05 13:52:33 2015 -0400 summary: Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. Patch by Gustavo J. A. M. Carneiro. files: Lib/asyncio/queues.py | 47 +++++++++-- Lib/test/test_asyncio/test_queues.py | 61 +++++++++++++++- Misc/NEWS | 3 + 3 files changed, 101 insertions(+), 10 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -47,7 +47,7 @@ # Futures. self._getters = collections.deque() - # Pairs of (item, Future). + # Futures self._putters = collections.deque() self._unfinished_tasks = 0 self._finished = locks.Event(loop=self._loop) @@ -98,7 +98,7 @@ def _consume_done_putters(self): # Delete waiters at the head of the put() queue who've timed out. - while self._putters and self._putters[0][1].done(): + while self._putters and self._putters[0].done(): self._putters.popleft() def qsize(self): @@ -148,8 +148,9 @@ elif self._maxsize > 0 and self._maxsize <= self.qsize(): waiter = futures.Future(loop=self._loop) - self._putters.append((item, waiter)) + self._putters.append(waiter) yield from waiter + self._put(item) else: self.__put_internal(item) @@ -186,8 +187,7 @@ self._consume_done_putters() if self._putters: assert self.full(), 'queue not full, why are putters waiting?' - item, putter = self._putters.popleft() - self.__put_internal(item) + putter = self._putters.popleft() # When a getter runs and frees up a slot so this putter can # run, we need to defer the put for a tick to ensure that @@ -201,9 +201,39 @@ return self._get() else: waiter = futures.Future(loop=self._loop) + self._getters.append(waiter) + try: + return (yield from waiter) + except futures.CancelledError: + # if we get CancelledError, it means someone cancelled this + # get() coroutine. But there is a chance that the waiter + # already is ready and contains an item that has just been + # removed from the queue. In this case, we need to put the item + # back into the front of the queue. This get() must either + # succeed without fault or, if it gets cancelled, it must be as + # if it never happened. + if waiter.done(): + self._put_it_back(waiter.result()) + raise - self._getters.append(waiter) - return (yield from waiter) + def _put_it_back(self, item): + """ + This is called when we have a waiter to get() an item and this waiter + gets cancelled. In this case, we put the item back: wake up another + waiter or put it in the _queue. + """ + self._consume_done_getters() + if self._getters: + assert not self._queue, ( + 'queue non-empty, why are getters waiting?') + + getter = self._getters.popleft() + self._put_internal(item) + + # getter cannot be cancelled, we just removed done getters + getter.set_result(item) + else: + self._queue.appendleft(item) def get_nowait(self): """Remove and return an item from the queue. @@ -213,8 +243,7 @@ self._consume_done_putters() if self._putters: assert self.full(), 'queue not full, why are putters waiting?' - item, putter = self._putters.popleft() - self.__put_internal(item) + putter = self._putters.popleft() # Wake putter on next tick. # getter cannot be cancelled, we just removed done putters diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -171,7 +171,7 @@ q.put_nowait(1) waiter = asyncio.Future(loop=self.loop) - q._putters.append((2, waiter)) + q._putters.append(waiter) res = self.loop.run_until_complete(q.get()) self.assertEqual(1, res) @@ -322,6 +322,64 @@ q.put_nowait(1) self.assertEqual(1, q.get_nowait()) + def test_get_cancel_drop(self): + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + + q = asyncio.Queue(loop=loop) + + reader = loop.create_task(q.get()) + + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + q.put_nowait(1) + q.put_nowait(2) + reader.cancel() + + try: + loop.run_until_complete(reader) + except asyncio.CancelledError: + # try again + reader = loop.create_task(q.get()) + loop.run_until_complete(reader) + + result = reader.result() + # if we get 2, it means 1 got dropped! + self.assertEqual(1, result) + + def test_put_cancel_drop(self): + + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + q = asyncio.Queue(1, loop=loop) + + q.put_nowait(1) + + # putting a second item in the queue has to block (qsize=1) + writer = loop.create_task(q.put(2)) + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + value1 = q.get_nowait() + self.assertEqual(value1, 1) + + writer.cancel() + try: + loop.run_until_complete(writer) + except asyncio.CancelledError: + # try again + writer = loop.create_task(q.put(2)) + loop.run_until_complete(writer) + + value2 = q.get_nowait() + self.assertEqual(value2, 2) + self.assertEqual(q.qsize(), 0) + def test_nonblocking_put_exception(self): q = asyncio.Queue(maxsize=1, loop=self.loop) q.put_nowait(1) @@ -374,6 +432,7 @@ test_utils.run_briefly(self.loop) self.assertTrue(put_c.done()) self.assertEqual(q.get_nowait(), 'a') + test_utils.run_briefly(self.loop) self.assertEqual(q.get_nowait(), 'b') self.loop.run_until_complete(put_b) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,6 +63,9 @@ - Issue #21354: PyCFunction_New function is exposed by python DLL again. +- Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. + Patch by Gustavo J. A. M. Carneiro. + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 19:59:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 17:59:02 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323812=3A_Fix_asyncio=2EQueue=2Eget=28=29_to_avoid_loo?= =?utf-8?q?sing_items_on_cancellation=2E?= Message-ID: <20150805175901.53977.71272@psf.io> https://hg.python.org/cpython/rev/d5644d7e222d changeset: 97278:d5644d7e222d branch: 3.5 parent: 97275:c29a1d78ed92 parent: 97277:7aa2d3e1c885 user: Yury Selivanov date: Wed Aug 05 13:55:54 2015 -0400 summary: Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. Patch by Gustavo J. A. M. Carneiro. files: Lib/asyncio/queues.py | 47 +++++++++-- Lib/test/test_asyncio/test_queues.py | 61 +++++++++++++++- Misc/NEWS | 3 + 3 files changed, 101 insertions(+), 10 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -47,7 +47,7 @@ # Futures. self._getters = collections.deque() - # Pairs of (item, Future). + # Futures self._putters = collections.deque() self._unfinished_tasks = 0 self._finished = locks.Event(loop=self._loop) @@ -98,7 +98,7 @@ def _consume_done_putters(self): # Delete waiters at the head of the put() queue who've timed out. - while self._putters and self._putters[0][1].done(): + while self._putters and self._putters[0].done(): self._putters.popleft() def qsize(self): @@ -148,8 +148,9 @@ elif self._maxsize > 0 and self._maxsize <= self.qsize(): waiter = futures.Future(loop=self._loop) - self._putters.append((item, waiter)) + self._putters.append(waiter) yield from waiter + self._put(item) else: self.__put_internal(item) @@ -186,8 +187,7 @@ self._consume_done_putters() if self._putters: assert self.full(), 'queue not full, why are putters waiting?' - item, putter = self._putters.popleft() - self.__put_internal(item) + putter = self._putters.popleft() # When a getter runs and frees up a slot so this putter can # run, we need to defer the put for a tick to ensure that @@ -201,9 +201,39 @@ return self._get() else: waiter = futures.Future(loop=self._loop) + self._getters.append(waiter) + try: + return (yield from waiter) + except futures.CancelledError: + # if we get CancelledError, it means someone cancelled this + # get() coroutine. But there is a chance that the waiter + # already is ready and contains an item that has just been + # removed from the queue. In this case, we need to put the item + # back into the front of the queue. This get() must either + # succeed without fault or, if it gets cancelled, it must be as + # if it never happened. + if waiter.done(): + self._put_it_back(waiter.result()) + raise - self._getters.append(waiter) - return (yield from waiter) + def _put_it_back(self, item): + """ + This is called when we have a waiter to get() an item and this waiter + gets cancelled. In this case, we put the item back: wake up another + waiter or put it in the _queue. + """ + self._consume_done_getters() + if self._getters: + assert not self._queue, ( + 'queue non-empty, why are getters waiting?') + + getter = self._getters.popleft() + self._put_internal(item) + + # getter cannot be cancelled, we just removed done getters + getter.set_result(item) + else: + self._queue.appendleft(item) def get_nowait(self): """Remove and return an item from the queue. @@ -213,8 +243,7 @@ self._consume_done_putters() if self._putters: assert self.full(), 'queue not full, why are putters waiting?' - item, putter = self._putters.popleft() - self.__put_internal(item) + putter = self._putters.popleft() # Wake putter on next tick. # getter cannot be cancelled, we just removed done putters diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -171,7 +171,7 @@ q.put_nowait(1) waiter = asyncio.Future(loop=self.loop) - q._putters.append((2, waiter)) + q._putters.append(waiter) res = self.loop.run_until_complete(q.get()) self.assertEqual(1, res) @@ -322,6 +322,64 @@ q.put_nowait(1) self.assertEqual(1, q.get_nowait()) + def test_get_cancel_drop(self): + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + + q = asyncio.Queue(loop=loop) + + reader = loop.create_task(q.get()) + + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + q.put_nowait(1) + q.put_nowait(2) + reader.cancel() + + try: + loop.run_until_complete(reader) + except asyncio.CancelledError: + # try again + reader = loop.create_task(q.get()) + loop.run_until_complete(reader) + + result = reader.result() + # if we get 2, it means 1 got dropped! + self.assertEqual(1, result) + + def test_put_cancel_drop(self): + + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + q = asyncio.Queue(1, loop=loop) + + q.put_nowait(1) + + # putting a second item in the queue has to block (qsize=1) + writer = loop.create_task(q.put(2)) + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + value1 = q.get_nowait() + self.assertEqual(value1, 1) + + writer.cancel() + try: + loop.run_until_complete(writer) + except asyncio.CancelledError: + # try again + writer = loop.create_task(q.put(2)) + loop.run_until_complete(writer) + + value2 = q.get_nowait() + self.assertEqual(value2, 2) + self.assertEqual(q.qsize(), 0) + def test_nonblocking_put_exception(self): q = asyncio.Queue(maxsize=1, loop=self.loop) q.put_nowait(1) @@ -374,6 +432,7 @@ test_utils.run_briefly(self.loop) self.assertTrue(put_c.done()) self.assertEqual(q.get_nowait(), 'a') + test_utils.run_briefly(self.loop) self.assertEqual(q.get_nowait(), 'b') self.loop.run_until_complete(put_b) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,9 @@ - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. +- Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. + Patch by Gustavo J. A. M. Carneiro. + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 19:59:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 17:59:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323812=3A_Fix_asyncio=2EQueue=2Eget=28=29_to_avo?= =?utf-8?q?id_loosing_items_on_cancellation=2E?= Message-ID: <20150805175902.23382.61824@psf.io> https://hg.python.org/cpython/rev/8f581da70ccd changeset: 97279:8f581da70ccd parent: 97276:e7b36ab053bf parent: 97278:d5644d7e222d user: Yury Selivanov date: Wed Aug 05 13:58:43 2015 -0400 summary: Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. Patch by Gustavo J. A. M. Carneiro. files: Lib/asyncio/queues.py | 47 +++++++++-- Lib/test/test_asyncio/test_queues.py | 61 +++++++++++++++- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -47,7 +47,7 @@ # Futures. self._getters = collections.deque() - # Pairs of (item, Future). + # Futures self._putters = collections.deque() self._unfinished_tasks = 0 self._finished = locks.Event(loop=self._loop) @@ -98,7 +98,7 @@ def _consume_done_putters(self): # Delete waiters at the head of the put() queue who've timed out. - while self._putters and self._putters[0][1].done(): + while self._putters and self._putters[0].done(): self._putters.popleft() def qsize(self): @@ -148,8 +148,9 @@ elif self._maxsize > 0 and self._maxsize <= self.qsize(): waiter = futures.Future(loop=self._loop) - self._putters.append((item, waiter)) + self._putters.append(waiter) yield from waiter + self._put(item) else: self.__put_internal(item) @@ -186,8 +187,7 @@ self._consume_done_putters() if self._putters: assert self.full(), 'queue not full, why are putters waiting?' - item, putter = self._putters.popleft() - self.__put_internal(item) + putter = self._putters.popleft() # When a getter runs and frees up a slot so this putter can # run, we need to defer the put for a tick to ensure that @@ -201,9 +201,39 @@ return self._get() else: waiter = futures.Future(loop=self._loop) + self._getters.append(waiter) + try: + return (yield from waiter) + except futures.CancelledError: + # if we get CancelledError, it means someone cancelled this + # get() coroutine. But there is a chance that the waiter + # already is ready and contains an item that has just been + # removed from the queue. In this case, we need to put the item + # back into the front of the queue. This get() must either + # succeed without fault or, if it gets cancelled, it must be as + # if it never happened. + if waiter.done(): + self._put_it_back(waiter.result()) + raise - self._getters.append(waiter) - return (yield from waiter) + def _put_it_back(self, item): + """ + This is called when we have a waiter to get() an item and this waiter + gets cancelled. In this case, we put the item back: wake up another + waiter or put it in the _queue. + """ + self._consume_done_getters() + if self._getters: + assert not self._queue, ( + 'queue non-empty, why are getters waiting?') + + getter = self._getters.popleft() + self._put_internal(item) + + # getter cannot be cancelled, we just removed done getters + getter.set_result(item) + else: + self._queue.appendleft(item) def get_nowait(self): """Remove and return an item from the queue. @@ -213,8 +243,7 @@ self._consume_done_putters() if self._putters: assert self.full(), 'queue not full, why are putters waiting?' - item, putter = self._putters.popleft() - self.__put_internal(item) + putter = self._putters.popleft() # Wake putter on next tick. # getter cannot be cancelled, we just removed done putters diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -171,7 +171,7 @@ q.put_nowait(1) waiter = asyncio.Future(loop=self.loop) - q._putters.append((2, waiter)) + q._putters.append(waiter) res = self.loop.run_until_complete(q.get()) self.assertEqual(1, res) @@ -322,6 +322,64 @@ q.put_nowait(1) self.assertEqual(1, q.get_nowait()) + def test_get_cancel_drop(self): + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + + q = asyncio.Queue(loop=loop) + + reader = loop.create_task(q.get()) + + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + q.put_nowait(1) + q.put_nowait(2) + reader.cancel() + + try: + loop.run_until_complete(reader) + except asyncio.CancelledError: + # try again + reader = loop.create_task(q.get()) + loop.run_until_complete(reader) + + result = reader.result() + # if we get 2, it means 1 got dropped! + self.assertEqual(1, result) + + def test_put_cancel_drop(self): + + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + q = asyncio.Queue(1, loop=loop) + + q.put_nowait(1) + + # putting a second item in the queue has to block (qsize=1) + writer = loop.create_task(q.put(2)) + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + value1 = q.get_nowait() + self.assertEqual(value1, 1) + + writer.cancel() + try: + loop.run_until_complete(writer) + except asyncio.CancelledError: + # try again + writer = loop.create_task(q.put(2)) + loop.run_until_complete(writer) + + value2 = q.get_nowait() + self.assertEqual(value2, 2) + self.assertEqual(q.qsize(), 0) + def test_nonblocking_put_exception(self): q = asyncio.Queue(maxsize=1, loop=self.loop) q.put_nowait(1) @@ -374,6 +432,7 @@ test_utils.run_briefly(self.loop) self.assertTrue(put_c.done()) self.assertEqual(q.get_nowait(), 'a') + test_utils.run_briefly(self.loop) self.assertEqual(q.get_nowait(), 'b') self.loop.run_until_complete(put_b) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:07:46 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 18:07:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogYXN5bmNpbzogTWFr?= =?utf-8?q?e_sure_BaseException_is_re-raised_in_SSLProtocol?= Message-ID: <20150805180742.23386.5453@psf.io> https://hg.python.org/cpython/rev/ee8e9edb8aae changeset: 97280:ee8e9edb8aae branch: 3.4 parent: 97277:7aa2d3e1c885 user: Yury Selivanov date: Wed Aug 05 14:06:23 2015 -0400 summary: asyncio: Make sure BaseException is re-raised in SSLProtocol files: Lib/asyncio/sslproto.py | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -613,7 +613,8 @@ if data: ssldata, offset = self._sslpipe.feed_appdata(data, offset) elif offset: - ssldata = self._sslpipe.do_handshake(self._on_handshake_complete) + ssldata = self._sslpipe.do_handshake( + self._on_handshake_complete) offset = 1 else: ssldata = self._sslpipe.shutdown(self._finalize) @@ -637,9 +638,13 @@ self._write_buffer_size -= len(data) except BaseException as exc: if self._in_handshake: + # BaseExceptions will be re-raised in _on_handshake_complete. self._on_handshake_complete(exc) else: self._fatal_error(exc, 'Fatal error on SSL transport') + if not isinstance(exc, Exception): + # BaseException + raise def _fatal_error(self, exc, message='Fatal error on transport'): # Should be called from exception handler only. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:07:46 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 18:07:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E5_=28asyncio=29?= Message-ID: <20150805180743.53985.71109@psf.io> https://hg.python.org/cpython/rev/95c0710ed0d9 changeset: 97282:95c0710ed0d9 parent: 97279:8f581da70ccd parent: 97281:332df8e8d244 user: Yury Selivanov date: Wed Aug 05 14:06:53 2015 -0400 summary: Merge 3.5 (asyncio) files: Lib/asyncio/sslproto.py | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -613,7 +613,8 @@ if data: ssldata, offset = self._sslpipe.feed_appdata(data, offset) elif offset: - ssldata = self._sslpipe.do_handshake(self._on_handshake_complete) + ssldata = self._sslpipe.do_handshake( + self._on_handshake_complete) offset = 1 else: ssldata = self._sslpipe.shutdown(self._finalize) @@ -637,9 +638,13 @@ self._write_buffer_size -= len(data) except BaseException as exc: if self._in_handshake: + # BaseExceptions will be re-raised in _on_handshake_complete. self._on_handshake_complete(exc) else: self._fatal_error(exc, 'Fatal error on SSL transport') + if not isinstance(exc, Exception): + # BaseException + raise def _fatal_error(self, exc, message='Fatal error on transport'): # Should be called from exception handler only. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:07:46 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 18:07:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28asyncio=29?= Message-ID: <20150805180743.41821.62610@psf.io> https://hg.python.org/cpython/rev/332df8e8d244 changeset: 97281:332df8e8d244 branch: 3.5 parent: 97278:d5644d7e222d parent: 97280:ee8e9edb8aae user: Yury Selivanov date: Wed Aug 05 14:06:38 2015 -0400 summary: Merge 3.4 (asyncio) files: Lib/asyncio/sslproto.py | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -613,7 +613,8 @@ if data: ssldata, offset = self._sslpipe.feed_appdata(data, offset) elif offset: - ssldata = self._sslpipe.do_handshake(self._on_handshake_complete) + ssldata = self._sslpipe.do_handshake( + self._on_handshake_complete) offset = 1 else: ssldata = self._sslpipe.shutdown(self._finalize) @@ -637,9 +638,13 @@ self._write_buffer_size -= len(data) except BaseException as exc: if self._in_handshake: + # BaseExceptions will be re-raised in _on_handshake_complete. self._on_handshake_complete(exc) else: self._fatal_error(exc, 'Fatal error on SSL transport') + if not isinstance(exc, Exception): + # BaseException + raise def _fatal_error(self, exc, message='Fatal error on transport'): # Should be called from exception handler only. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:36:33 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 05 Aug 2015 18:36:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogRml4ZXMgbWFrZV96?= =?utf-8?q?ip=2Epy_to_create_temporary_=2Epyc_files_in_a_separate_director?= =?utf-8?q?y=2E_This?= Message-ID: <20150805183632.29400.57381@psf.io> https://hg.python.org/cpython/rev/9575858d45a4 changeset: 97283:9575858d45a4 branch: 3.5 parent: 97281:332df8e8d244 user: Steve Dower date: Wed Aug 05 11:34:50 2015 -0700 summary: Fixes make_zip.py to create temporary .pyc files in a separate directory. This avoids polluting tests that run code from TEMP. files: Tools/msi/make_zip.py | 23 ++++++++++++----------- 1 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -82,18 +82,19 @@ target.unlink() with ZipFile(str(target), 'w', ZIP_DEFLATED) as f: - for s, rel in rel_sources: - if rel.suffix.lower() == '.py': - pyc = Path(tempfile.gettempdir()) / rel.with_suffix('.pyc').name - try: - py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) - except py_compile.PyCompileError: + with tempfile.TemporaryDirectory() as tmpdir: + for s, rel in rel_sources: + if rel.suffix.lower() == '.py': + pyc = Path(tmpdir) / rel.with_suffix('.pyc').name + try: + py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) + except py_compile.PyCompileError: + f.write(str(s), str(rel)) + else: + f.write(str(pyc), str(rel.with_suffix('.pyc'))) + else: f.write(str(s), str(rel)) - else: - f.write(str(pyc), str(rel.with_suffix('.pyc'))) - else: - f.write(str(s), str(rel)) - count += 1 + count += 1 else: for s, rel in rel_sources: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:36:34 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 05 Aug 2015 18:36:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150805183633.53989.38264@psf.io> https://hg.python.org/cpython/rev/fe4e2ae492d4 changeset: 97284:fe4e2ae492d4 parent: 97282:95c0710ed0d9 parent: 97283:9575858d45a4 user: Steve Dower date: Wed Aug 05 11:35:36 2015 -0700 summary: Merge with 3.5 files: Tools/msi/make_zip.py | 23 ++++++++++++----------- 1 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -82,18 +82,19 @@ target.unlink() with ZipFile(str(target), 'w', ZIP_DEFLATED) as f: - for s, rel in rel_sources: - if rel.suffix.lower() == '.py': - pyc = Path(tempfile.gettempdir()) / rel.with_suffix('.pyc').name - try: - py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) - except py_compile.PyCompileError: + with tempfile.TemporaryDirectory() as tmpdir: + for s, rel in rel_sources: + if rel.suffix.lower() == '.py': + pyc = Path(tmpdir) / rel.with_suffix('.pyc').name + try: + py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) + except py_compile.PyCompileError: + f.write(str(s), str(rel)) + else: + f.write(str(pyc), str(rel.with_suffix('.pyc'))) + else: f.write(str(s), str(rel)) - else: - f.write(str(pyc), str(rel.with_suffix('.pyc'))) - else: - f.write(str(s), str(rel)) - count += 1 + count += 1 else: for s, rel in rel_sources: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:48:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 18:48:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogYXN5bmNpby50ZXN0?= =?utf-8?q?=5Fpep492=3A_Add_a_test_for_asyncio=2Eiscoroutinefunction?= Message-ID: <20150805184829.111165.52525@psf.io> https://hg.python.org/cpython/rev/17129db11be3 changeset: 97285:17129db11be3 branch: 3.5 parent: 97283:9575858d45a4 user: Yury Selivanov date: Wed Aug 05 14:47:33 2015 -0400 summary: asyncio.test_pep492: Add a test for asyncio.iscoroutinefunction files: Lib/test/test_asyncio/test_pep492.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -107,6 +107,10 @@ self.assertTrue(asyncio.iscoroutine(FakeCoro())) + def test_iscoroutinefunction(self): + async def foo(): pass + self.assertTrue(asyncio.iscoroutinefunction(foo)) + def test_function_returning_awaitable(self): class Awaitable: def __await__(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:48:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 18:48:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E5_=28asyncio=29?= Message-ID: <20150805184829.5531.80515@psf.io> https://hg.python.org/cpython/rev/301e53491af0 changeset: 97286:301e53491af0 parent: 97284:fe4e2ae492d4 parent: 97285:17129db11be3 user: Yury Selivanov date: Wed Aug 05 14:47:47 2015 -0400 summary: Merge 3.5 (asyncio) files: Lib/test/test_asyncio/test_pep492.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -107,6 +107,10 @@ self.assertTrue(asyncio.iscoroutine(FakeCoro())) + def test_iscoroutinefunction(self): + async def foo(): pass + self.assertTrue(asyncio.iscoroutinefunction(foo)) + def test_function_returning_awaitable(self): class Awaitable: def __await__(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:50:13 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 05 Aug 2015 18:50:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150805185013.1389.27261@psf.io> https://hg.python.org/cpython/rev/1db9dbf62c3f changeset: 97288:1db9dbf62c3f parent: 97286:301e53491af0 parent: 97287:34b35aa1967d user: Steve Dower date: Wed Aug 05 11:49:20 2015 -0700 summary: Merge with 3.5 files: Lib/distutils/command/wininst-14.0-amd64.exe | Bin Lib/distutils/command/wininst-14.0.exe | Bin 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Lib/distutils/command/wininst-14.0-amd64.exe b/Lib/distutils/command/wininst-14.0-amd64.exe index 43b85b6d4f2dd93f4b77c4b904276293ff667054..7a5e78d52bcc5db0be1baff6cdad41e172a5b81f GIT binary patch [stripped] diff --git a/Lib/distutils/command/wininst-14.0.exe b/Lib/distutils/command/wininst-14.0.exe index 764524d746b35fe28228e41e8b75a6ed665d9228..cc43296b677a5b995899bb60bbe0e632163e64ae GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 20:50:13 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 05 Aug 2015 18:50:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Rebuild_winins?= =?utf-8?q?t-14=2E0=5B-amd64=5D=2Eexe_with_updated_tools=2E?= Message-ID: <20150805185013.29392.45403@psf.io> https://hg.python.org/cpython/rev/34b35aa1967d changeset: 97287:34b35aa1967d branch: 3.5 parent: 97285:17129db11be3 user: Steve Dower date: Wed Aug 05 11:48:14 2015 -0700 summary: Rebuild wininst-14.0[-amd64].exe with updated tools. files: Lib/distutils/command/wininst-14.0-amd64.exe | Bin Lib/distutils/command/wininst-14.0.exe | Bin 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Lib/distutils/command/wininst-14.0-amd64.exe b/Lib/distutils/command/wininst-14.0-amd64.exe index 43b85b6d4f2dd93f4b77c4b904276293ff667054..7a5e78d52bcc5db0be1baff6cdad41e172a5b81f GIT binary patch [stripped] diff --git a/Lib/distutils/command/wininst-14.0.exe b/Lib/distutils/command/wininst-14.0.exe index 764524d746b35fe28228e41e8b75a6ed665d9228..cc43296b677a5b995899bb60bbe0e632163e64ae GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 23:55:28 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 21:55:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Nzkx?= =?utf-8?q?=3A_Fix_grammar_regression_for_call_syntax=3A_=27g=28*a_or_b=29?= =?utf-8?b?Jy4=?= Message-ID: <20150805215528.53979.86308@psf.io> https://hg.python.org/cpython/rev/e4cb64628673 changeset: 97289:e4cb64628673 branch: 3.5 parent: 97287:34b35aa1967d user: Yury Selivanov date: Wed Aug 05 17:54:10 2015 -0400 summary: Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. files: Grammar/Grammar | 2 +- Lib/test/test_grammar.py | 2 + Misc/NEWS | 2 + Modules/parsermodule.c | 9 ++- Python/ast.c | 65 +++++++++++++-------------- Python/graminit.c | 2 +- 6 files changed, 44 insertions(+), 38 deletions(-) diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -137,7 +137,7 @@ argument: ( test [comp_for] | test '=' test | '**' test | - star_expr ) + '*' test ) comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -205,6 +205,8 @@ d01() d01(1) d01(*(1,)) + d01(*[] or [2]) + d01(*() or (), *{} and (), **() or {}) d01(**{'a':2}) d01(**{'a':2} or {}) def d11(a, b=1): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,8 @@ - Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. Patch by Gustavo J. A. M. Carneiro. +- Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. + Documentation ------------- diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -2859,8 +2859,8 @@ /* argument: ( test [comp_for] | * test '=' test | - * '**' expr | - * star_expr ) + * '**' test | + * '*' test ) */ static int validate_argument(node *tree) @@ -2873,8 +2873,11 @@ if (TYPE(CHILD(tree, 0)) == DOUBLESTAR) { res = validate_test(CHILD(tree, 1)); } + else if (TYPE(CHILD(tree, 0)) == STAR) { + res = validate_test(CHILD(tree, 1)); + } else if (nch == 1) { - res = validate_test_or_star_expr(CHILD(tree, 0)); + res = validate_test(CHILD(tree, 0)); } else if (nch == 2) { res = (validate_test(CHILD(tree, 0)) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -2664,45 +2664,44 @@ expr_ty e; node *chch = CHILD(ch, 0); if (NCH(ch) == 1) { - if (TYPE(chch) == star_expr) { - /* an iterable argument unpacking */ - expr_ty starred; + /* a positional argument */ + if (nkeywords) { if (ndoublestars) { ast_error(c, chch, - "iterable argument unpacking follows " + "positional argument follows " "keyword argument unpacking"); - return NULL; } - e = ast_for_expr(c, CHILD(chch, 1)); - if (!e) - return NULL; - starred = Starred(e, Load, LINENO(chch), - chch->n_col_offset, - c->c_arena); - if (!starred) - return NULL; - asdl_seq_SET(args, nargs++, starred); + else { + ast_error(c, chch, + "positional argument follows " + "keyword argument"); + } + return NULL; } - else { - /* a positional argument */ - if (nkeywords) { - if (ndoublestars) { - ast_error(c, chch, - "positional argument follows " - "keyword argument unpacking"); - } - else { - ast_error(c, chch, - "positional argument follows " - "keyword argument"); - } - return NULL; - } - e = ast_for_expr(c, chch); - if (!e) - return NULL; - asdl_seq_SET(args, nargs++, e); + e = ast_for_expr(c, chch); + if (!e) + return NULL; + asdl_seq_SET(args, nargs++, e); + } + else if (TYPE(chch) == STAR) { + /* an iterable argument unpacking */ + expr_ty starred; + if (ndoublestars) { + ast_error(c, chch, + "iterable argument unpacking follows " + "keyword argument unpacking"); + return NULL; } + e = ast_for_expr(c, CHILD(ch, 1)); + if (!e) + return NULL; + starred = Starred(e, Load, LINENO(chch), + chch->n_col_offset, + c->c_arena); + if (!starred) + return NULL; + asdl_seq_SET(args, nargs++, starred); + } else if (TYPE(chch) == DOUBLESTAR) { /* a keyword argument unpacking */ diff --git a/Python/graminit.c b/Python/graminit.c --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1744,7 +1744,7 @@ static arc arcs_78_0[3] = { {26, 1}, {34, 2}, - {50, 3}, + {33, 2}, }; static arc arcs_78_1[3] = { {164, 3}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 5 23:55:28 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 21:55:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZSAjMjQ3OTEp?= Message-ID: <20150805215528.23404.78762@psf.io> https://hg.python.org/cpython/rev/4c89dd5199e5 changeset: 97290:4c89dd5199e5 parent: 97288:1db9dbf62c3f parent: 97289:e4cb64628673 user: Yury Selivanov date: Wed Aug 05 17:55:12 2015 -0400 summary: Merge 3.5 (issue #24791) files: Grammar/Grammar | 2 +- Lib/test/test_grammar.py | 2 + Modules/parsermodule.c | 9 ++- Python/ast.c | 65 +++++++++++++-------------- Python/graminit.c | 2 +- 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -137,7 +137,7 @@ argument: ( test [comp_for] | test '=' test | '**' test | - star_expr ) + '*' test ) comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' or_test [comp_iter] diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -205,6 +205,8 @@ d01() d01(1) d01(*(1,)) + d01(*[] or [2]) + d01(*() or (), *{} and (), **() or {}) d01(**{'a':2}) d01(**{'a':2} or {}) def d11(a, b=1): pass diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -2859,8 +2859,8 @@ /* argument: ( test [comp_for] | * test '=' test | - * '**' expr | - * star_expr ) + * '**' test | + * '*' test ) */ static int validate_argument(node *tree) @@ -2873,8 +2873,11 @@ if (TYPE(CHILD(tree, 0)) == DOUBLESTAR) { res = validate_test(CHILD(tree, 1)); } + else if (TYPE(CHILD(tree, 0)) == STAR) { + res = validate_test(CHILD(tree, 1)); + } else if (nch == 1) { - res = validate_test_or_star_expr(CHILD(tree, 0)); + res = validate_test(CHILD(tree, 0)); } else if (nch == 2) { res = (validate_test(CHILD(tree, 0)) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -2664,45 +2664,44 @@ expr_ty e; node *chch = CHILD(ch, 0); if (NCH(ch) == 1) { - if (TYPE(chch) == star_expr) { - /* an iterable argument unpacking */ - expr_ty starred; + /* a positional argument */ + if (nkeywords) { if (ndoublestars) { ast_error(c, chch, - "iterable argument unpacking follows " + "positional argument follows " "keyword argument unpacking"); - return NULL; } - e = ast_for_expr(c, CHILD(chch, 1)); - if (!e) - return NULL; - starred = Starred(e, Load, LINENO(chch), - chch->n_col_offset, - c->c_arena); - if (!starred) - return NULL; - asdl_seq_SET(args, nargs++, starred); + else { + ast_error(c, chch, + "positional argument follows " + "keyword argument"); + } + return NULL; } - else { - /* a positional argument */ - if (nkeywords) { - if (ndoublestars) { - ast_error(c, chch, - "positional argument follows " - "keyword argument unpacking"); - } - else { - ast_error(c, chch, - "positional argument follows " - "keyword argument"); - } - return NULL; - } - e = ast_for_expr(c, chch); - if (!e) - return NULL; - asdl_seq_SET(args, nargs++, e); + e = ast_for_expr(c, chch); + if (!e) + return NULL; + asdl_seq_SET(args, nargs++, e); + } + else if (TYPE(chch) == STAR) { + /* an iterable argument unpacking */ + expr_ty starred; + if (ndoublestars) { + ast_error(c, chch, + "iterable argument unpacking follows " + "keyword argument unpacking"); + return NULL; } + e = ast_for_expr(c, CHILD(ch, 1)); + if (!e) + return NULL; + starred = Starred(e, Load, LINENO(chch), + chch->n_col_offset, + c->c_arena); + if (!starred) + return NULL; + asdl_seq_SET(args, nargs++, starred); + } else if (TYPE(chch) == DOUBLESTAR) { /* a keyword argument unpacking */ diff --git a/Python/graminit.c b/Python/graminit.c --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1744,7 +1744,7 @@ static arc arcs_78_0[3] = { {26, 1}, {34, 2}, - {50, 3}, + {33, 2}, }; static arc arcs_78_1[3] = { {164, 3}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 00:00:38 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 22:00:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E5_=28issue_=2324791=3B_more_tests_in_test=5Fpa?= =?utf-8?q?rser=29?= Message-ID: <20150805220036.41849.5816@psf.io> https://hg.python.org/cpython/rev/a572137b4f05 changeset: 97292:a572137b4f05 parent: 97290:4c89dd5199e5 parent: 97291:40c391d12741 user: Yury Selivanov date: Wed Aug 05 18:00:11 2015 -0400 summary: Merge 3.5 (issue #24791; more tests in test_parser) files: Lib/test/test_parser.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -350,9 +350,11 @@ self.check_expr('{**{}, 3:4, **{5:6, 7:8}}') def test_argument_unpacking(self): + self.check_expr("f(*a, **b)") self.check_expr('f(a, *b, *c, *d)') self.check_expr('f(**a, **b)') self.check_expr('f(2, *a, *b, **b, **c, **d)') + self.check_expr("f(*b, *() or () and (), **{} and {}, **() or {})") def test_set_comprehensions(self): self.check_expr('{x for x in seq}') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 00:00:38 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 22:00:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Nzkx?= =?utf-8?q?=3A_More_tests_in_test=5Fparser?= Message-ID: <20150805220036.53979.6624@psf.io> https://hg.python.org/cpython/rev/40c391d12741 changeset: 97291:40c391d12741 branch: 3.5 parent: 97289:e4cb64628673 user: Yury Selivanov date: Wed Aug 05 17:59:45 2015 -0400 summary: Issue #24791: More tests in test_parser files: Lib/test/test_parser.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -350,9 +350,11 @@ self.check_expr('{**{}, 3:4, **{5:6, 7:8}}') def test_argument_unpacking(self): + self.check_expr("f(*a, **b)") self.check_expr('f(a, *b, *c, *d)') self.check_expr('f(**a, **b)') self.check_expr('f(2, *a, *b, **b, **c, **d)') + self.check_expr("f(*b, *() or () and (), **{} and {}, **() or {})") def test_set_comprehensions(self): self.check_expr('{x for x in seq}') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 01:02:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 23:02:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogd2hhdHNuZXcvMy41?= =?utf-8?q?=3A_Mention_new_ssl_memory_bio?= Message-ID: <20150805230222.29416.83305@psf.io> https://hg.python.org/cpython/rev/4721805fc35d changeset: 97293:4721805fc35d branch: 3.5 parent: 97291:40c391d12741 user: Yury Selivanov date: Wed Aug 05 19:01:51 2015 -0400 summary: whatsnew/3.5: Mention new ssl memory bio files: Doc/whatsnew/3.5.rst | 19 ++++++++++++++----- 1 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -114,6 +114,10 @@ :func:`gettempdirb` and :func:`gettempprefixb`, have been added to go along with this. This behavior matches that of the :mod:`os` APIs. +* :mod:`ssl` module gained support for Memory BIO, which decouples SSL + protocol handling from network IO. (Contributed by Geert Jansen in + :issue:`21965`.) + Security improvements: * None yet. @@ -825,11 +829,16 @@ ssl --- -The :meth:`~ssl.SSLSocket.do_handshake`, :meth:`~ssl.SSLSocket.read`, -:meth:`~ssl.SSLSocket.shutdown`, and :meth:`~ssl.SSLSocket.write` methods of -:class:`ssl.SSLSocket` don't reset the socket timeout anymore each time bytes -are received or sent. The socket timeout is now the maximum total duration of -the method. +* The :meth:`~ssl.SSLSocket.do_handshake`, :meth:`~ssl.SSLSocket.read`, + :meth:`~ssl.SSLSocket.shutdown`, and :meth:`~ssl.SSLSocket.write` methods of + :class:`ssl.SSLSocket` don't reset the socket timeout anymore each time bytes + are received or sent. The socket timeout is now the maximum total duration of + the method. + +* Memory BIO Support: new classes :class:`~ssl.SSLObject`, + :class:`~ssl.MemoryBIO`, and new + :meth:`SSLContext.wrap_bio ` method. + (Contributed by Geert Jansen in :issue:`21965`.) socket ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 01:02:22 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 05 Aug 2015 23:02:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150805230222.29398.57391@psf.io> https://hg.python.org/cpython/rev/2a12f69b32e8 changeset: 97294:2a12f69b32e8 parent: 97292:a572137b4f05 parent: 97293:4721805fc35d user: Yury Selivanov date: Wed Aug 05 19:02:03 2015 -0400 summary: Merge 3.5 files: Doc/whatsnew/3.5.rst | 19 ++++++++++++++----- 1 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -114,6 +114,10 @@ :func:`gettempdirb` and :func:`gettempprefixb`, have been added to go along with this. This behavior matches that of the :mod:`os` APIs. +* :mod:`ssl` module gained support for Memory BIO, which decouples SSL + protocol handling from network IO. (Contributed by Geert Jansen in + :issue:`21965`.) + Security improvements: * None yet. @@ -825,11 +829,16 @@ ssl --- -The :meth:`~ssl.SSLSocket.do_handshake`, :meth:`~ssl.SSLSocket.read`, -:meth:`~ssl.SSLSocket.shutdown`, and :meth:`~ssl.SSLSocket.write` methods of -:class:`ssl.SSLSocket` don't reset the socket timeout anymore each time bytes -are received or sent. The socket timeout is now the maximum total duration of -the method. +* The :meth:`~ssl.SSLSocket.do_handshake`, :meth:`~ssl.SSLSocket.read`, + :meth:`~ssl.SSLSocket.shutdown`, and :meth:`~ssl.SSLSocket.write` methods of + :class:`ssl.SSLSocket` don't reset the socket timeout anymore each time bytes + are received or sent. The socket timeout is now the maximum total duration of + the method. + +* Memory BIO Support: new classes :class:`~ssl.SSLObject`, + :class:`~ssl.MemoryBIO`, and new + :meth:`SSLContext.wrap_bio ` method. + (Contributed by Geert Jansen in :issue:`21965`.) socket ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 06:55:39 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 06 Aug 2015 04:55:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323672=3AMerge_with_3=2E4?= Message-ID: <20150806045539.23404.46912@psf.io> https://hg.python.org/cpython/rev/97d50e6247e1 changeset: 97296:97d50e6247e1 branch: 3.5 parent: 97293:4721805fc35d parent: 97295:dda625798111 user: Terry Jan Reedy date: Thu Aug 06 00:54:45 2015 -0400 summary: Issue #23672:Merge with 3.4 files: Lib/idlelib/EditorWindow.py | 16 ++++++++-------- Lib/idlelib/ScriptBinding.py | 4 +++- Lib/idlelib/idle_test/test_editor.py | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -344,19 +344,19 @@ def _filename_to_unicode(self, filename): - """convert filename to unicode in order to display it in Tk""" - if isinstance(filename, str) or not filename: - return filename - else: + """Return filename as BMP unicode so diplayable in Tk.""" + # Decode bytes to unicode. + if isinstance(filename, bytes): try: - return filename.decode(self.filesystemencoding) + filename = filename.decode(self.filesystemencoding) except UnicodeDecodeError: - # XXX try: - return filename.decode(self.encoding) + filename = filename.decode(self.encoding) except UnicodeDecodeError: # byte-to-byte conversion - return filename.decode('iso8859-1') + filename = filename.decode('iso8859-1') + # Replace non-BMP char with diamond questionmark. + return re.sub('[\U00010000-\U0010FFFF]', '\ufffd', filename) def new_callback(self, event): dirname, basename = self.io.defaultfilename() diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -36,6 +36,7 @@ by Format->Untabify Region and specify the number of columns used by each tab. """ + class ScriptBinding: menudefs = [ @@ -142,7 +143,8 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False, filename=code.co_filename) + interp.restart_subprocess(with_cwd=False, filename= + self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py new file mode 100644 --- /dev/null +++ b/Lib/idlelib/idle_test/test_editor.py @@ -0,0 +1,16 @@ +import unittest +from tkinter import Tk, Text +from idlelib.EditorWindow import EditorWindow +from test.support import requires + +class Editor_func_test(unittest.TestCase): + def test_filename_to_unicode(self): + func = EditorWindow._filename_to_unicode + class dummy(): filesystemencoding = 'utf-8' + pairs = (('abc', 'abc'), ('a\U00011111c', 'a\ufffdc'), + (b'abc', 'abc'), (b'a\xf0\x91\x84\x91c', 'a\ufffdc')) + for inp, out in pairs: + self.assertEqual(func(dummy, inp), out) + +if __name__ == '__main__': + unittest.main(verbosity=2) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 06:55:39 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 06 Aug 2015 04:55:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNjcy?= =?utf-8?q?=3A_Allow_Idle_to_edit_and_run_files_with_astral_chars_in_name?= =?utf-8?q?=2E?= Message-ID: <20150806045539.41839.53150@psf.io> https://hg.python.org/cpython/rev/dda625798111 changeset: 97295:dda625798111 branch: 3.4 parent: 97280:ee8e9edb8aae user: Terry Jan Reedy date: Thu Aug 06 00:54:07 2015 -0400 summary: Issue #23672: Allow Idle to edit and run files with astral chars in name. Patch by Mohd Sanad Zaki Rizvi. files: Lib/idlelib/EditorWindow.py | 16 ++++++++-------- Lib/idlelib/ScriptBinding.py | 4 +++- Lib/idlelib/idle_test/test_editor.py | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -344,19 +344,19 @@ def _filename_to_unicode(self, filename): - """convert filename to unicode in order to display it in Tk""" - if isinstance(filename, str) or not filename: - return filename - else: + """Return filename as BMP unicode so diplayable in Tk.""" + # Decode bytes to unicode. + if isinstance(filename, bytes): try: - return filename.decode(self.filesystemencoding) + filename = filename.decode(self.filesystemencoding) except UnicodeDecodeError: - # XXX try: - return filename.decode(self.encoding) + filename = filename.decode(self.encoding) except UnicodeDecodeError: # byte-to-byte conversion - return filename.decode('iso8859-1') + filename = filename.decode('iso8859-1') + # Replace non-BMP char with diamond questionmark. + return re.sub('[\U00010000-\U0010FFFF]', '\ufffd', filename) def new_callback(self, event): dirname, basename = self.io.defaultfilename() diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -36,6 +36,7 @@ by Format->Untabify Region and specify the number of columns used by each tab. """ + class ScriptBinding: menudefs = [ @@ -142,7 +143,8 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False, filename=code.co_filename) + interp.restart_subprocess(with_cwd=False, filename= + self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py new file mode 100644 --- /dev/null +++ b/Lib/idlelib/idle_test/test_editor.py @@ -0,0 +1,16 @@ +import unittest +from tkinter import Tk, Text +from idlelib.EditorWindow import EditorWindow +from test.support import requires + +class Editor_func_test(unittest.TestCase): + def test_filename_to_unicode(self): + func = EditorWindow._filename_to_unicode + class dummy(): filesystemencoding = 'utf-8' + pairs = (('abc', 'abc'), ('a\U00011111c', 'a\ufffdc'), + (b'abc', 'abc'), (b'a\xf0\x91\x84\x91c', 'a\ufffdc')) + for inp, out in pairs: + self.assertEqual(func(dummy, inp), out) + +if __name__ == '__main__': + unittest.main(verbosity=2) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 06:55:40 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 06 Aug 2015 04:55:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323672=3AMerge_with_3=2E5?= Message-ID: <20150806045539.23406.29632@psf.io> https://hg.python.org/cpython/rev/180bfaa7cdf8 changeset: 97297:180bfaa7cdf8 parent: 97294:2a12f69b32e8 parent: 97296:97d50e6247e1 user: Terry Jan Reedy date: Thu Aug 06 00:55:07 2015 -0400 summary: Issue #23672:Merge with 3.5 files: Lib/idlelib/EditorWindow.py | 16 ++++++++-------- Lib/idlelib/ScriptBinding.py | 4 +++- Lib/idlelib/idle_test/test_editor.py | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -344,19 +344,19 @@ def _filename_to_unicode(self, filename): - """convert filename to unicode in order to display it in Tk""" - if isinstance(filename, str) or not filename: - return filename - else: + """Return filename as BMP unicode so diplayable in Tk.""" + # Decode bytes to unicode. + if isinstance(filename, bytes): try: - return filename.decode(self.filesystemencoding) + filename = filename.decode(self.filesystemencoding) except UnicodeDecodeError: - # XXX try: - return filename.decode(self.encoding) + filename = filename.decode(self.encoding) except UnicodeDecodeError: # byte-to-byte conversion - return filename.decode('iso8859-1') + filename = filename.decode('iso8859-1') + # Replace non-BMP char with diamond questionmark. + return re.sub('[\U00010000-\U0010FFFF]', '\ufffd', filename) def new_callback(self, event): dirname, basename = self.io.defaultfilename() diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -36,6 +36,7 @@ by Format->Untabify Region and specify the number of columns used by each tab. """ + class ScriptBinding: menudefs = [ @@ -142,7 +143,8 @@ return 'break' interp = self.shell.interp if PyShell.use_subprocess: - interp.restart_subprocess(with_cwd=False, filename=code.co_filename) + interp.restart_subprocess(with_cwd=False, filename= + self.editwin._filename_to_unicode(filename)) dirname = os.path.dirname(filename) # XXX Too often this discards arguments the user just set... interp.runcommand("""if 1: diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py new file mode 100644 --- /dev/null +++ b/Lib/idlelib/idle_test/test_editor.py @@ -0,0 +1,16 @@ +import unittest +from tkinter import Tk, Text +from idlelib.EditorWindow import EditorWindow +from test.support import requires + +class Editor_func_test(unittest.TestCase): + def test_filename_to_unicode(self): + func = EditorWindow._filename_to_unicode + class dummy(): filesystemencoding = 'utf-8' + pairs = (('abc', 'abc'), ('a\U00011111c', 'a\ufffdc'), + (b'abc', 'abc'), (b'a\xf0\x91\x84\x91c', 'a\ufffdc')) + for inp, out in pairs: + self.assertEqual(func(dummy, inp), out) + +if __name__ == '__main__': + unittest.main(verbosity=2) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 07:06:07 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 06 Aug 2015 05:06:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxMjc5?= =?utf-8?q?=3A_Flesh_out_str=2Etranslate_docs?= Message-ID: <20150806050607.5521.57714@psf.io> https://hg.python.org/cpython/rev/ae53bd5decae changeset: 97298:ae53bd5decae branch: 3.4 parent: 97295:dda625798111 user: Zachary Ware date: Wed Aug 05 23:54:15 2015 -0500 summary: Issue #21279: Flesh out str.translate docs Initial patch by Kinga Farkas, Martin Panter, and John Posner. files: Doc/library/stdtypes.rst | 23 ++++++++++++----------- Objects/unicodeobject.c | 11 ++++++----- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1976,21 +1976,22 @@ "They're Bill's Friends." -.. method:: str.translate(map) - - Return a copy of the *s* where all characters have been mapped through the - *map* which must be a dictionary of Unicode ordinals (integers) to Unicode - ordinals, strings or ``None``. Unmapped characters are left untouched. - Characters mapped to ``None`` are deleted. +.. method:: str.translate(table) + + Return a copy of the string in which each character has been mapped through + the given translation table. The table must be an object that implements + indexing via :meth:`__getitem__`, typically a :term:`mapping` or + :term:`sequence`. When indexed by a Unicode ordinal (an integer), the + table object can do any of the following: return a Unicode ordinal or a + string, to map the character to one or more other characters; return + ``None``, to delete the character from the return string; or raise a + :exc:`LookupError` exception, to map the character to itself. You can use :meth:`str.maketrans` to create a translation map from character-to-character mappings in different formats. - .. note:: - - An even more flexible approach is to create a custom character mapping - codec using the :mod:`codecs` module (see :mod:`encodings.cp1251` for an - example). + See also the :mod:`codecs` module for a more flexible approach to custom + character mappings. .. method:: str.upper() diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13077,11 +13077,12 @@ PyDoc_STRVAR(translate__doc__, "S.translate(table) -> str\n\ \n\ -Return a copy of the string S, where all characters have been mapped\n\ -through the given translation table, which must be a mapping of\n\ -Unicode ordinals to Unicode ordinals, strings, or None.\n\ -Unmapped characters are left untouched. Characters mapped to None\n\ -are deleted."); +Return a copy of the string S in which each character has been mapped\n\ +through the given translation table. The table must implement\n\ +lookup/indexing via __getitem__, for instance a dictionary or list,\n\ +mapping Unicode ordinals to Unicode ordinals, strings, or None. If\n\ +this operation raises LookupError, the character is left untouched.\n\ +Characters mapped to None are deleted."); static PyObject* unicode_translate(PyObject *self, PyObject *table) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 07:06:08 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 06 Aug 2015 05:06:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2321279=3A_Merge_with_3=2E5?= Message-ID: <20150806050608.29400.22948@psf.io> https://hg.python.org/cpython/rev/967c9a9fe724 changeset: 97300:967c9a9fe724 parent: 97297:180bfaa7cdf8 parent: 97299:064b569e38fe user: Zachary Ware date: Thu Aug 06 00:05:13 2015 -0500 summary: Closes #21279: Merge with 3.5 files: Doc/library/stdtypes.rst | 23 ++++++++++++----------- Objects/unicodeobject.c | 11 ++++++----- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1986,21 +1986,22 @@ "They're Bill's Friends." -.. method:: str.translate(map) - - Return a copy of the *s* where all characters have been mapped through the - *map* which must be a dictionary of Unicode ordinals (integers) to Unicode - ordinals, strings or ``None``. Unmapped characters are left untouched. - Characters mapped to ``None`` are deleted. +.. method:: str.translate(table) + + Return a copy of the string in which each character has been mapped through + the given translation table. The table must be an object that implements + indexing via :meth:`__getitem__`, typically a :term:`mapping` or + :term:`sequence`. When indexed by a Unicode ordinal (an integer), the + table object can do any of the following: return a Unicode ordinal or a + string, to map the character to one or more other characters; return + ``None``, to delete the character from the return string; or raise a + :exc:`LookupError` exception, to map the character to itself. You can use :meth:`str.maketrans` to create a translation map from character-to-character mappings in different formats. - .. note:: - - An even more flexible approach is to create a custom character mapping - codec using the :mod:`codecs` module (see :mod:`encodings.cp1251` for an - example). + See also the :mod:`codecs` module for a more flexible approach to custom + character mappings. .. method:: str.upper() diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13038,11 +13038,12 @@ PyDoc_STRVAR(translate__doc__, "S.translate(table) -> str\n\ \n\ -Return a copy of the string S, where all characters have been mapped\n\ -through the given translation table, which must be a mapping of\n\ -Unicode ordinals to Unicode ordinals, strings, or None.\n\ -Unmapped characters are left untouched. Characters mapped to None\n\ -are deleted."); +Return a copy of the string S in which each character has been mapped\n\ +through the given translation table. The table must implement\n\ +lookup/indexing via __getitem__, for instance a dictionary or list,\n\ +mapping Unicode ordinals to Unicode ordinals, strings, or None. If\n\ +this operation raises LookupError, the character is left untouched.\n\ +Characters mapped to None are deleted."); static PyObject* unicode_translate(PyObject *self, PyObject *table) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 07:06:09 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 06 Aug 2015 05:06:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2321279=3A_Merge_with_3=2E4?= Message-ID: <20150806050608.94788.53952@psf.io> https://hg.python.org/cpython/rev/064b569e38fe changeset: 97299:064b569e38fe branch: 3.5 parent: 97296:97d50e6247e1 parent: 97298:ae53bd5decae user: Zachary Ware date: Thu Aug 06 00:04:23 2015 -0500 summary: Issue #21279: Merge with 3.4 files: Doc/library/stdtypes.rst | 23 ++++++++++++----------- Objects/unicodeobject.c | 11 ++++++----- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1986,21 +1986,22 @@ "They're Bill's Friends." -.. method:: str.translate(map) - - Return a copy of the *s* where all characters have been mapped through the - *map* which must be a dictionary of Unicode ordinals (integers) to Unicode - ordinals, strings or ``None``. Unmapped characters are left untouched. - Characters mapped to ``None`` are deleted. +.. method:: str.translate(table) + + Return a copy of the string in which each character has been mapped through + the given translation table. The table must be an object that implements + indexing via :meth:`__getitem__`, typically a :term:`mapping` or + :term:`sequence`. When indexed by a Unicode ordinal (an integer), the + table object can do any of the following: return a Unicode ordinal or a + string, to map the character to one or more other characters; return + ``None``, to delete the character from the return string; or raise a + :exc:`LookupError` exception, to map the character to itself. You can use :meth:`str.maketrans` to create a translation map from character-to-character mappings in different formats. - .. note:: - - An even more flexible approach is to create a custom character mapping - codec using the :mod:`codecs` module (see :mod:`encodings.cp1251` for an - example). + See also the :mod:`codecs` module for a more flexible approach to custom + character mappings. .. method:: str.upper() diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13031,11 +13031,12 @@ PyDoc_STRVAR(translate__doc__, "S.translate(table) -> str\n\ \n\ -Return a copy of the string S, where all characters have been mapped\n\ -through the given translation table, which must be a mapping of\n\ -Unicode ordinals to Unicode ordinals, strings, or None.\n\ -Unmapped characters are left untouched. Characters mapped to None\n\ -are deleted."); +Return a copy of the string S in which each character has been mapped\n\ +through the given translation table. The table must implement\n\ +lookup/indexing via __getitem__, for instance a dictionary or list,\n\ +mapping Unicode ordinals to Unicode ordinals, strings, or None. If\n\ +this operation raises LookupError, the character is left untouched.\n\ +Characters mapped to None are deleted."); static PyObject* unicode_translate(PyObject *self, PyObject *table) -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Thu Aug 6 10:12:42 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Thu, 6 Aug 2015 08:12:42 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-06 Message-ID: Results for project python_default-nightly, build date 2015-08-06 09:01:51 commit: 967c9a9fe724fba37b12713d2380ba81c9d734cc revision date: 2015-08-06 08:05:13 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec -0.91679% -3.92493% :-( regex_v8 sec 0.51907% -3.20197% :-| nbody sec 0.02207% -0.41902% :-| json_dump_v2 sec 0.33721% -1.28650% :-| normal_startup sec -0.03697% -0.01499% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From solipsis at pitrou.net Thu Aug 6 10:47:45 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 06 Aug 2015 08:47:45 +0000 Subject: [Python-checkins] Daily reference leaks (967c9a9fe724): sum=7 Message-ID: <20150806084745.94792.47143@psf.io> results for 967c9a9fe724 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_functools leaked [0, 2, 2] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogWIeh6F', '--timeout', '7200'] From python-checkins at python.org Thu Aug 6 11:15:14 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 06 Aug 2015 09:15:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324531=3A_Document_that_encoding_lines_cannot_fo?= =?utf-8?q?llow_non-comment_lines=2E?= Message-ID: <20150806091514.110979.27181@psf.io> https://hg.python.org/cpython/rev/82c9ce30c0a0 changeset: 97304:82c9ce30c0a0 parent: 97300:967c9a9fe724 parent: 97303:caecc1869921 user: Robert Collins date: Thu Aug 06 21:14:48 2015 +1200 summary: Issue #24531: Document that encoding lines cannot follow non-comment lines. Patch from Terry Reedy files: Doc/reference/lexical_analysis.rst | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -81,7 +81,9 @@ If a comment in the first or second line of the Python script matches the regular expression ``coding[=:]\s*([-\w.]+)``, this comment is processed as an encoding declaration; the first group of this expression names the encoding of -the source code file. The recommended forms of this expression are :: +the source code file. The encoding declaration must appear on a line of its +own. If it is the second line, the first line must also be a comment-only line. +The recommended forms of an encoding expression are :: # -*- coding: -*- @@ -98,7 +100,7 @@ If an encoding is declared, the encoding name must be recognized by Python. The encoding is used for all lexical analysis, including string literals, comments -and identifiers. The encoding declaration must appear on a line of its own. +and identifiers. .. XXX there should be a list of supported encodings. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 11:15:14 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 06 Aug 2015 09:15:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NTMx?= =?utf-8?q?=3A_Document_that_encoding_lines_cannot_follow_non-comment_line?= =?utf-8?q?s=2E?= Message-ID: <20150806091513.29408.86658@psf.io> https://hg.python.org/cpython/rev/08e03dfb7dab changeset: 97301:08e03dfb7dab branch: 2.7 parent: 97257:6987a9c7dde9 user: Robert Collins date: Thu Aug 06 21:08:44 2015 +1200 summary: Issue #24531: Document that encoding lines cannot follow non-comment lines. Patch from Terry Reedy files: Doc/reference/lexical_analysis.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -109,7 +109,9 @@ If a comment in the first or second line of the Python script matches the regular expression ``coding[=:]\s*([-\w.]+)``, this comment is processed as an encoding declaration; the first group of this expression names the encoding of -the source code file. The recommended forms of this expression are :: +the source code file. The encoding declaration must appear on a line of its +own. If it is the second line, the first line must also be a comment-only line. +The recommended forms of an encoding expression are :: # -*- coding: -*- @@ -126,8 +128,7 @@ encoding is used for all lexical analysis, in particular to find the end of a string, and to interpret the contents of Unicode literals. String literals are converted to Unicode for syntactical analysis, then converted back to their -original encoding before interpretation starts. The encoding declaration must -appear on a line of its own. +original encoding before interpretation starts. .. XXX there should be a list of supported encodings. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 11:15:14 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 06 Aug 2015 09:15:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324531=3A_Document_that_encoding_lines_cannot_follow_n?= =?utf-8?q?on-comment_lines=2E?= Message-ID: <20150806091513.1387.83628@psf.io> https://hg.python.org/cpython/rev/caecc1869921 changeset: 97303:caecc1869921 branch: 3.5 parent: 97299:064b569e38fe parent: 97302:ab75b7ff4dfe user: Robert Collins date: Thu Aug 06 21:14:34 2015 +1200 summary: Issue #24531: Document that encoding lines cannot follow non-comment lines. Patch from Terry Reedy files: Doc/reference/lexical_analysis.rst | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -81,7 +81,9 @@ If a comment in the first or second line of the Python script matches the regular expression ``coding[=:]\s*([-\w.]+)``, this comment is processed as an encoding declaration; the first group of this expression names the encoding of -the source code file. The recommended forms of this expression are :: +the source code file. The encoding declaration must appear on a line of its +own. If it is the second line, the first line must also be a comment-only line. +The recommended forms of an encoding expression are :: # -*- coding: -*- @@ -98,7 +100,7 @@ If an encoding is declared, the encoding name must be recognized by Python. The encoding is used for all lexical analysis, including string literals, comments -and identifiers. The encoding declaration must appear on a line of its own. +and identifiers. .. XXX there should be a list of supported encodings. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 11:15:14 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 06 Aug 2015 09:15:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NTMx?= =?utf-8?q?=3A_Document_that_encoding_lines_cannot_follow_non-comment_line?= =?utf-8?q?s=2E?= Message-ID: <20150806091513.17737.37466@psf.io> https://hg.python.org/cpython/rev/ab75b7ff4dfe changeset: 97302:ab75b7ff4dfe branch: 3.4 parent: 97298:ae53bd5decae user: Robert Collins date: Thu Aug 06 21:08:44 2015 +1200 summary: Issue #24531: Document that encoding lines cannot follow non-comment lines. Patch from Terry Reedy files: Doc/reference/lexical_analysis.rst | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -81,7 +81,9 @@ If a comment in the first or second line of the Python script matches the regular expression ``coding[=:]\s*([-\w.]+)``, this comment is processed as an encoding declaration; the first group of this expression names the encoding of -the source code file. The recommended forms of this expression are :: +the source code file. The encoding declaration must appear on a line of its +own. If it is the second line, the first line must also be a comment-only line. +The recommended forms of an encoding expression are :: # -*- coding: -*- @@ -98,7 +100,7 @@ If an encoding is declared, the encoding name must be recognized by Python. The encoding is used for all lexical analysis, including string literals, comments -and identifiers. The encoding declaration must appear on a line of its own. +and identifiers. .. XXX there should be a list of supported encodings. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 12:17:39 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 06 Aug 2015 10:17:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMDA0?= =?utf-8?q?=3A_mock=5Fopen=28=29_now_reads_binary_data_correctly_when_the_?= =?utf-8?q?type_of?= Message-ID: <20150806101739.1383.34051@psf.io> https://hg.python.org/cpython/rev/3d7adf5b3fb3 changeset: 97305:3d7adf5b3fb3 branch: 3.4 parent: 97302:ab75b7ff4dfe user: Berker Peksag date: Thu Aug 06 13:15:51 2015 +0300 summary: Issue #23004: mock_open() now reads binary data correctly when the type of read_data is bytes. Initial patch by Aaron Hill. files: Lib/unittest/mock.py | 9 ++-- Lib/unittest/test/testmock/testwith.py | 28 ++++++++++++++ Misc/NEWS | 3 + 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2250,9 +2250,10 @@ # Helper for mock_open: # Retrieve lines from read_data via a generator so that separate calls to # readline, read, and readlines are properly interleaved - data_as_list = ['{}\n'.format(l) for l in read_data.split('\n')] - - if data_as_list[-1] == '\n': + sep = b'\n' if isinstance(read_data, bytes) else '\n' + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: # If the last line ended in a newline, the list comprehension will have an # extra entry that's just a newline. Remove this. data_as_list = data_as_list[:-1] @@ -2286,7 +2287,7 @@ def _read_side_effect(*args, **kwargs): if handle.read.return_value is not None: return handle.read.return_value - return ''.join(_state[0]) + return type(read_data)().join(_state[0]) def _readline_side_effect(): if handle.readline.return_value is not None: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -224,6 +224,34 @@ self.assertEqual(result, ['foo\n', 'bar\n', 'baz']) + def test_read_bytes(self): + mock = mock_open(read_data=b'\xc6') + with patch('%s.open' % __name__, mock, create=True): + with open('abc', 'rb') as f: + result = f.read() + self.assertEqual(result, b'\xc6') + + + def test_readline_bytes(self): + m = mock_open(read_data=b'abc\ndef\nghi\n') + with patch('%s.open' % __name__, m, create=True): + with open('abc', 'rb') as f: + line1 = f.readline() + line2 = f.readline() + line3 = f.readline() + self.assertEqual(line1, b'abc\n') + self.assertEqual(line2, b'def\n') + self.assertEqual(line3, b'ghi\n') + + + def test_readlines_bytes(self): + m = mock_open(read_data=b'abc\ndef\nghi\n') + with patch('%s.open' % __name__, m, create=True): + with open('abc', 'rb') as f: + result = f.readlines() + self.assertEqual(result, [b'abc\n', b'def\n', b'ghi\n']) + + def test_mock_open_read_with_argument(self): # At one point calling read with an argument was broken # for mocks returned by mock_open diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -71,6 +71,9 @@ - Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. +- Issue #23004: mock_open() now reads binary data correctly when the type of + read_data is bytes. Initial patch by Aaron Hill. + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Patch by Matt Frank. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 12:17:39 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 06 Aug 2015 10:17:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323004=3A_mock=5Fopen=28=29_now_reads_binary_dat?= =?utf-8?q?a_correctly_when_the_type_of?= Message-ID: <20150806101739.53967.97059@psf.io> https://hg.python.org/cpython/rev/ed15f399a292 changeset: 97307:ed15f399a292 parent: 97304:82c9ce30c0a0 parent: 97306:526a186de32d user: Berker Peksag date: Thu Aug 06 13:17:27 2015 +0300 summary: Issue #23004: mock_open() now reads binary data correctly when the type of read_data is bytes. Initial patch by Aaron Hill. files: Lib/unittest/mock.py | 9 ++-- Lib/unittest/test/testmock/testwith.py | 28 ++++++++++++++ Misc/NEWS | 3 + 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2271,9 +2271,10 @@ # Helper for mock_open: # Retrieve lines from read_data via a generator so that separate calls to # readline, read, and readlines are properly interleaved - data_as_list = ['{}\n'.format(l) for l in read_data.split('\n')] - - if data_as_list[-1] == '\n': + sep = b'\n' if isinstance(read_data, bytes) else '\n' + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: # If the last line ended in a newline, the list comprehension will have an # extra entry that's just a newline. Remove this. data_as_list = data_as_list[:-1] @@ -2307,7 +2308,7 @@ def _read_side_effect(*args, **kwargs): if handle.read.return_value is not None: return handle.read.return_value - return ''.join(_state[0]) + return type(read_data)().join(_state[0]) def _readline_side_effect(): if handle.readline.return_value is not None: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -224,6 +224,34 @@ self.assertEqual(result, ['foo\n', 'bar\n', 'baz']) + def test_read_bytes(self): + mock = mock_open(read_data=b'\xc6') + with patch('%s.open' % __name__, mock, create=True): + with open('abc', 'rb') as f: + result = f.read() + self.assertEqual(result, b'\xc6') + + + def test_readline_bytes(self): + m = mock_open(read_data=b'abc\ndef\nghi\n') + with patch('%s.open' % __name__, m, create=True): + with open('abc', 'rb') as f: + line1 = f.readline() + line2 = f.readline() + line3 = f.readline() + self.assertEqual(line1, b'abc\n') + self.assertEqual(line2, b'def\n') + self.assertEqual(line3, b'ghi\n') + + + def test_readlines_bytes(self): + m = mock_open(read_data=b'abc\ndef\nghi\n') + with patch('%s.open' % __name__, m, create=True): + with open('abc', 'rb') as f: + result = f.readlines() + self.assertEqual(result, [b'abc\n', b'def\n', b'ghi\n']) + + def test_mock_open_read_with_argument(self): # At one point calling read with an argument was broken # for mocks returned by mock_open diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ - Issue #23973: Update typing.py from GitHub repo. +- Issue #23004: mock_open() now reads binary data correctly when the type of + read_data is bytes. Initial patch by Aaron Hill. + - Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. - Issue #23652: Make it possible to compile the select module against the -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 12:17:39 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 06 Aug 2015 10:17:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2323004=3A_mock=5Fopen=28=29_now_reads_binary_data_corr?= =?utf-8?q?ectly_when_the_type_of?= Message-ID: <20150806101739.5533.34047@psf.io> https://hg.python.org/cpython/rev/526a186de32d changeset: 97306:526a186de32d branch: 3.5 parent: 97303:caecc1869921 parent: 97305:3d7adf5b3fb3 user: Berker Peksag date: Thu Aug 06 13:16:52 2015 +0300 summary: Issue #23004: mock_open() now reads binary data correctly when the type of read_data is bytes. Initial patch by Aaron Hill. files: Lib/unittest/mock.py | 9 ++-- Lib/unittest/test/testmock/testwith.py | 28 ++++++++++++++ Misc/NEWS | 3 + 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2271,9 +2271,10 @@ # Helper for mock_open: # Retrieve lines from read_data via a generator so that separate calls to # readline, read, and readlines are properly interleaved - data_as_list = ['{}\n'.format(l) for l in read_data.split('\n')] - - if data_as_list[-1] == '\n': + sep = b'\n' if isinstance(read_data, bytes) else '\n' + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: # If the last line ended in a newline, the list comprehension will have an # extra entry that's just a newline. Remove this. data_as_list = data_as_list[:-1] @@ -2307,7 +2308,7 @@ def _read_side_effect(*args, **kwargs): if handle.read.return_value is not None: return handle.read.return_value - return ''.join(_state[0]) + return type(read_data)().join(_state[0]) def _readline_side_effect(): if handle.readline.return_value is not None: diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -224,6 +224,34 @@ self.assertEqual(result, ['foo\n', 'bar\n', 'baz']) + def test_read_bytes(self): + mock = mock_open(read_data=b'\xc6') + with patch('%s.open' % __name__, mock, create=True): + with open('abc', 'rb') as f: + result = f.read() + self.assertEqual(result, b'\xc6') + + + def test_readline_bytes(self): + m = mock_open(read_data=b'abc\ndef\nghi\n') + with patch('%s.open' % __name__, m, create=True): + with open('abc', 'rb') as f: + line1 = f.readline() + line2 = f.readline() + line3 = f.readline() + self.assertEqual(line1, b'abc\n') + self.assertEqual(line2, b'def\n') + self.assertEqual(line3, b'ghi\n') + + + def test_readlines_bytes(self): + m = mock_open(read_data=b'abc\ndef\nghi\n') + with patch('%s.open' % __name__, m, create=True): + with open('abc', 'rb') as f: + result = f.readlines() + self.assertEqual(result, [b'abc\n', b'def\n', b'ghi\n']) + + def test_mock_open_read_with_argument(self): # At one point calling read with an argument was broken # for mocks returned by mock_open diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ - Issue #23973: Update typing.py from GitHub repo. +- Issue #23004: mock_open() now reads binary data correctly when the type of + read_data is bytes. Initial patch by Aaron Hill. + - Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. - Issue #23652: Make it possible to compile the select module against the -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 20:04:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 06 Aug 2015 18:04:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODEy?= =?utf-8?q?=3A_Fix_getter-cancellation_with_many_pending_getters_code_path?= Message-ID: <20150806180445.17709.40864@psf.io> https://hg.python.org/cpython/rev/024d4f4011c9 changeset: 97308:024d4f4011c9 branch: 3.4 parent: 97305:3d7adf5b3fb3 user: Yury Selivanov date: Thu Aug 06 14:03:38 2015 -0400 summary: Issue #23812: Fix getter-cancellation with many pending getters code path files: Lib/asyncio/queues.py | 2 +- Lib/test/test_asyncio/test_queues.py | 37 +++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -228,7 +228,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put_internal(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(item) diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -322,7 +322,7 @@ q.put_nowait(1) self.assertEqual(1, q.get_nowait()) - def test_get_cancel_drop(self): + def test_get_cancel_drop_one_pending_reader(self): def gen(): yield 0.01 yield 0.1 @@ -350,6 +350,41 @@ # if we get 2, it means 1 got dropped! self.assertEqual(1, result) + def test_get_cancel_drop_many_pending_readers(self): + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + loop.set_debug(True) + + q = asyncio.Queue(loop=loop) + + reader1 = loop.create_task(q.get()) + reader2 = loop.create_task(q.get()) + reader3 = loop.create_task(q.get()) + + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + q.put_nowait(1) + q.put_nowait(2) + reader1.cancel() + + try: + loop.run_until_complete(reader1) + except asyncio.CancelledError: + pass + + loop.run_until_complete(reader3) + + # reader2 will receive `2`, because it was added to the + # queue of pending readers *before* put_nowaits were called. + self.assertEqual(reader2.result(), 2) + # reader3 will receive `1`, because reader1 was cancelled + # before is had a chance to execute, and `2` was already + # pushed to reader2 by second `put_nowait`. + self.assertEqual(reader3.result(), 1) + def test_put_cancel_drop(self): def gen(): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 20:04:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 06 Aug 2015 18:04:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZSAjMjM4MTIp?= Message-ID: <20150806180446.41845.59371@psf.io> https://hg.python.org/cpython/rev/e54c684e6788 changeset: 97310:e54c684e6788 parent: 97307:ed15f399a292 parent: 97309:2752fe734bfb user: Yury Selivanov date: Thu Aug 06 14:04:30 2015 -0400 summary: Merge 3.5 (issue #23812) files: Lib/asyncio/queues.py | 2 +- Lib/test/test_asyncio/test_queues.py | 37 +++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -228,7 +228,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put_internal(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(item) diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -322,7 +322,7 @@ q.put_nowait(1) self.assertEqual(1, q.get_nowait()) - def test_get_cancel_drop(self): + def test_get_cancel_drop_one_pending_reader(self): def gen(): yield 0.01 yield 0.1 @@ -350,6 +350,41 @@ # if we get 2, it means 1 got dropped! self.assertEqual(1, result) + def test_get_cancel_drop_many_pending_readers(self): + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + loop.set_debug(True) + + q = asyncio.Queue(loop=loop) + + reader1 = loop.create_task(q.get()) + reader2 = loop.create_task(q.get()) + reader3 = loop.create_task(q.get()) + + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + q.put_nowait(1) + q.put_nowait(2) + reader1.cancel() + + try: + loop.run_until_complete(reader1) + except asyncio.CancelledError: + pass + + loop.run_until_complete(reader3) + + # reader2 will receive `2`, because it was added to the + # queue of pending readers *before* put_nowaits were called. + self.assertEqual(reader2.result(), 2) + # reader3 will receive `1`, because reader1 was cancelled + # before is had a chance to execute, and `2` was already + # pushed to reader2 by second `put_nowait`. + self.assertEqual(reader3.result(), 1) + def test_put_cancel_drop(self): def gen(): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 6 20:04:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 06 Aug 2015 18:04:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28issue_=2323812=29?= Message-ID: <20150806180445.53975.31621@psf.io> https://hg.python.org/cpython/rev/2752fe734bfb changeset: 97309:2752fe734bfb branch: 3.5 parent: 97306:526a186de32d parent: 97308:024d4f4011c9 user: Yury Selivanov date: Thu Aug 06 14:04:12 2015 -0400 summary: Merge 3.4 (issue #23812) files: Lib/asyncio/queues.py | 2 +- Lib/test/test_asyncio/test_queues.py | 37 +++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -228,7 +228,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put_internal(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(item) diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -322,7 +322,7 @@ q.put_nowait(1) self.assertEqual(1, q.get_nowait()) - def test_get_cancel_drop(self): + def test_get_cancel_drop_one_pending_reader(self): def gen(): yield 0.01 yield 0.1 @@ -350,6 +350,41 @@ # if we get 2, it means 1 got dropped! self.assertEqual(1, result) + def test_get_cancel_drop_many_pending_readers(self): + def gen(): + yield 0.01 + yield 0.1 + + loop = self.new_test_loop(gen) + loop.set_debug(True) + + q = asyncio.Queue(loop=loop) + + reader1 = loop.create_task(q.get()) + reader2 = loop.create_task(q.get()) + reader3 = loop.create_task(q.get()) + + loop.run_until_complete(asyncio.sleep(0.01, loop=loop)) + + q.put_nowait(1) + q.put_nowait(2) + reader1.cancel() + + try: + loop.run_until_complete(reader1) + except asyncio.CancelledError: + pass + + loop.run_until_complete(reader3) + + # reader2 will receive `2`, because it was added to the + # queue of pending readers *before* put_nowaits were called. + self.assertEqual(reader2.result(), 2) + # reader3 will receive `1`, because reader1 was cancelled + # before is had a chance to execute, and `2` was already + # pushed to reader2 by second `put_nowait`. + self.assertEqual(reader3.result(), 1) + def test_put_cancel_drop(self): def gen(): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 7 00:34:50 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 06 Aug 2015 22:34:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=234395=3A_Better_testing_and_documentation_of_binary_op?= =?utf-8?q?erators=2E?= Message-ID: <20150806223450.23412.78466@psf.io> https://hg.python.org/cpython/rev/b9a0165a3de8 changeset: 97312:b9a0165a3de8 branch: 3.5 parent: 97309:2752fe734bfb parent: 97311:f5069e6e4229 user: Robert Collins date: Fri Aug 07 10:32:15 2015 +1200 summary: Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. files: Doc/reference/datamodel.rst | 22 +++++++++++++--------- Lib/test/test_binop.py | 22 +++++++++++++++++++++- Misc/NEWS | 3 +++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1276,10 +1276,14 @@ context (e.g., in the condition of an ``if`` statement), Python will call :func:`bool` on the value to determine if the result is true or false. - There are no implied relationships among the comparison operators. The truth - of ``x==y`` does not imply that ``x!=y`` is false. Accordingly, when - defining :meth:`__eq__`, one should also define :meth:`__ne__` so that the - operators will behave as expected. See the paragraph on :meth:`__hash__` for + By default, :meth:`__ne__` delegates to :meth:`__eq__` and + inverts the result unless it is ``NotImplemented``. There are no other + implied relationships among the comparison operators, for example, + the truth of ``(x https://hg.python.org/cpython/rev/f5069e6e4229 changeset: 97311:f5069e6e4229 branch: 3.4 parent: 97308:024d4f4011c9 user: Robert Collins date: Fri Aug 07 10:22:54 2015 +1200 summary: Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. files: Doc/reference/datamodel.rst | 22 +++++++++++++--------- Lib/test/test_binop.py | 23 ++++++++++++++++++++++- Misc/NEWS | 3 +++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1266,10 +1266,14 @@ context (e.g., in the condition of an ``if`` statement), Python will call :func:`bool` on the value to determine if the result is true or false. - There are no implied relationships among the comparison operators. The truth - of ``x==y`` does not imply that ``x!=y`` is false. Accordingly, when - defining :meth:`__eq__`, one should also define :meth:`__ne__` so that the - operators will behave as expected. See the paragraph on :meth:`__hash__` for + By default, :meth:`__ne__` delegates to :meth:`__eq__` and + inverts the result unless it is ``NotImplemented``. There are no other + implied relationships among the comparison operators, for example, + the truth of ``(x https://hg.python.org/cpython/rev/e56893df8e76 changeset: 97313:e56893df8e76 parent: 97310:e54c684e6788 parent: 97312:b9a0165a3de8 user: Robert Collins date: Fri Aug 07 10:34:23 2015 +1200 summary: Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. files: Doc/reference/datamodel.rst | 22 +++++++++++++--------- Lib/test/test_binop.py | 22 +++++++++++++++++++++- Misc/NEWS | 3 +++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1276,10 +1276,14 @@ context (e.g., in the condition of an ``if`` statement), Python will call :func:`bool` on the value to determine if the result is true or false. - There are no implied relationships among the comparison operators. The truth - of ``x==y`` does not imply that ``x!=y`` is false. Accordingly, when - defining :meth:`__eq__`, one should also define :meth:`__ne__` so that the - operators will behave as expected. See the paragraph on :meth:`__hash__` for + By default, :meth:`__ne__` delegates to :meth:`__eq__` and + inverts the result unless it is ``NotImplemented``. There are no other + implied relationships among the comparison operators, for example, + the truth of ``(x https://hg.python.org/cpython/rev/226d379b351e changeset: 97314:226d379b351e user: Raymond Hettinger date: Thu Aug 06 22:15:22 2015 -0700 summary: Restore frozenset hash caching removed in cf707dd190a9 files: Objects/setobject.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -763,6 +763,9 @@ Py_uhash_t hash = 1927868237UL; setentry *entry; + if (so->hash != -1) + return so->hash; + /* Initial dispersion based on the number of active entries */ hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 7 09:43:51 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 07 Aug 2015 07:43:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Move_the_active_entry_mult?= =?utf-8?q?iplication_to_later_in_the_hash_calculation?= Message-ID: <20150807074351.94766.76462@psf.io> https://hg.python.org/cpython/rev/2c124e30a324 changeset: 97315:2c124e30a324 user: Raymond Hettinger date: Fri Aug 07 00:43:39 2015 -0700 summary: Move the active entry multiplication to later in the hash calculation files: Objects/setobject.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -760,15 +760,12 @@ frozenset_hash(PyObject *self) { PySetObject *so = (PySetObject *)self; - Py_uhash_t hash = 1927868237UL; + Py_uhash_t hash = 0; setentry *entry; if (so->hash != -1) return so->hash; - /* Initial dispersion based on the number of active entries */ - hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1; - /* Xor-in shuffled bits from every entry's hash field because xor is commutative and a frozenset hash should be independent of order. @@ -790,6 +787,9 @@ if ((so->fill - so->used) & 1) hash ^= _shuffle_bits(-1); + /* Factor in the number of active entries */ + hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL; + /* Disperse patterns arising in nested frozensets */ hash = hash * 69069U + 907133923UL; -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Fri Aug 7 09:48:51 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Fri, 7 Aug 2015 07:48:51 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-07 Message-ID: Results for project python_default-nightly, build date 2015-08-07 09:02:36 commit: 226d379b351e41842de6834998c5c331f6b83020 revision date: 2015-08-07 08:15:22 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec 1.57515% -2.28795% :-( regex_v8 sec -0.73565% -3.96118% :-| nbody sec -0.45394% -0.87486% :-| json_dump_v2 sec 0.32647% -0.95583% :-| normal_startup sec 0.07453% 0.05955% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Fri Aug 7 23:39:37 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 07 Aug 2015 21:39:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324798=3A_=5Fmsvccompiler=2Epy_doesn=27t_properl?= =?utf-8?q?y_support_manifests?= Message-ID: <20150807213936.17713.75333@psf.io> https://hg.python.org/cpython/rev/f61a083b843f changeset: 97317:f61a083b843f parent: 97315:2c124e30a324 parent: 97316:8e966eba2b5e user: Steve Dower date: Fri Aug 07 14:36:02 2015 -0700 summary: Issue #24798: _msvccompiler.py doesn't properly support manifests files: Lib/distutils/_msvccompiler.py | 167 +++------- Lib/distutils/tests/test_msvccompiler.py | 121 ------- 2 files changed, 50 insertions(+), 238 deletions(-) diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -15,7 +15,6 @@ import os import subprocess -import re from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ CompileError, LibError, LinkError @@ -182,7 +181,8 @@ raise DistutilsPlatformError("Unable to find a compatible " "Visual Studio installation.") - paths = vc_env.get('path', '').split(os.pathsep) + self._paths = vc_env.get('path', '') + paths = self._paths.split(os.pathsep) self.cc = _find_exe("cl.exe", paths) self.linker = _find_exe("link.exe", paths) self.lib = _find_exe("lib.exe", paths) @@ -199,22 +199,40 @@ self.add_library_dir(dir) self.preprocess_options = None + # Use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib + # later to dynamically link to ucrtbase but not vcruntime. self.compile_options = [ - '/nologo', '/Ox', '/MD', '/W3', '/GL', '/DNDEBUG' + '/nologo', '/Ox', '/MT', '/W3', '/GL', '/DNDEBUG' ] self.compile_options_debug = [ - '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' + '/nologo', '/Od', '/MTd', '/Zi', '/W3', '/D_DEBUG' ] - self.ldflags_shared = [ - '/nologo', '/DLL', '/INCREMENTAL:NO', '/LTCG', '/nodefaultlib:libucrt.lib', 'ucrt.lib' + ldflags = [ + '/nologo', '/INCREMENTAL:NO', '/LTCG', '/nodefaultlib:libucrt.lib', 'ucrt.lib', ] - self.ldflags_shared_debug = [ - '/nologo', '/DLL', '/INCREMENTAL:no', '/LTCG', '/DEBUG:FULL', '/nodefaultlib:libucrtd.lib', 'ucrtd.lib' + ldflags_debug = [ + '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL', '/nodefaultlib:libucrtd.lib', 'ucrtd.lib', ] - self.ldflags_static = [ - '/nologo' - ] + + self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1'] + self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1'] + self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO'] + self.ldflags_shared_debug = [*ldflags_debug, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO'] + self.ldflags_static = [*ldflags] + self.ldflags_static_debug = [*ldflags_debug] + + self._ldflags = { + (CCompiler.EXECUTABLE, None): self.ldflags_exe, + (CCompiler.EXECUTABLE, False): self.ldflags_exe, + (CCompiler.EXECUTABLE, True): self.ldflags_exe_debug, + (CCompiler.SHARED_OBJECT, None): self.ldflags_shared, + (CCompiler.SHARED_OBJECT, False): self.ldflags_shared, + (CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug, + (CCompiler.SHARED_LIBRARY, None): self.ldflags_static, + (CCompiler.SHARED_LIBRARY, False): self.ldflags_static, + (CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug, + } self.initialized = True @@ -224,9 +242,12 @@ source_filenames, strip_dir=0, output_dir=''): - ext_map = {ext: self.obj_extension for ext in self.src_extensions} - ext_map.update((ext, self.res_extension) - for ext in self._rc_extensions + self._mc_extensions) + ext_map = { + **{ext: self.obj_extension for ext in self.src_extensions}, + **{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions}, + } + + output_dir = output_dir or '' def make_out_path(p): base, ext = os.path.splitext(p) @@ -237,18 +258,17 @@ if base.startswith((os.path.sep, os.path.altsep)): base = base[1:] try: - return base + ext_map[ext] + # XXX: This may produce absurdly long paths. We should check + # the length of the result and trim base until we fit within + # 260 characters. + return os.path.join(output_dir, base + ext_map[ext]) except LookupError: # Better to raise an exception instead of silently continuing # and later complain about sources and targets having # different lengths raise CompileError("Don't know how to compile {}".format(p)) - output_dir = output_dir or '' - return [ - os.path.join(output_dir, make_out_path(src_name)) - for src_name in source_filenames - ] + return list(map(make_out_path, source_filenames)) def compile(self, sources, @@ -359,6 +379,7 @@ if debug: pass # XXX what goes here? try: + log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args)) self.spawn([self.lib] + lib_args) except DistutilsExecError as msg: raise LibError(msg) @@ -399,14 +420,9 @@ output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): - ldflags = (self.ldflags_shared_debug if debug - else self.ldflags_shared) - if target_desc == CCompiler.EXECUTABLE: - ldflags = ldflags[1:] + ldflags = self._ldflags[target_desc, debug] - export_opts = [] - for sym in (export_symbols or []): - export_opts.append("/EXPORT:" + sym) + export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])] ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) @@ -425,8 +441,6 @@ self.library_filename(dll_name)) ld_args.append ('/IMPLIB:' + implib_file) - self.manifest_setup_ldargs(output_filename, build_temp, ld_args) - if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: @@ -434,101 +448,20 @@ self.mkpath(os.path.dirname(output_filename)) try: + log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) - - # embed the manifest - # XXX - this is somewhat fragile - if mt.exe fails, distutils - # will still consider the DLL up-to-date, but it will not have a - # manifest. Maybe we should link to a temp file? OTOH, that - # implies a build environment error that shouldn't go undetected. - mfinfo = self.manifest_get_embed_info(target_desc, ld_args) - if mfinfo is not None: - mffilename, mfid = mfinfo - out_arg = '-outputresource:{};{}'.format(output_filename, mfid) - try: - self.spawn([self.mt, '-nologo', '-manifest', - mffilename, out_arg]) - except DistutilsExecError as msg: - raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) - def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): - # If we need a manifest at all, an embedded manifest is recommended. - # See MSDN article titled - # "How to: Embed a Manifest Inside a C/C++ Application" - # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) - # Ask the linker to generate the manifest in the temp dir, so - # we can check it, and possibly embed it, later. - temp_manifest = os.path.join( - build_temp, - os.path.basename(output_filename) + ".manifest") - ld_args.append('/MANIFESTFILE:' + temp_manifest) - - def manifest_get_embed_info(self, target_desc, ld_args): - # If a manifest should be embedded, return a tuple of - # (manifest_filename, resource_id). Returns None if no manifest - # should be embedded. See http://bugs.python.org/issue7833 for why - # we want to avoid any manifest for extension modules if we can) - for arg in ld_args: - if arg.startswith("/MANIFESTFILE:"): - temp_manifest = arg.split(":", 1)[1] - break - else: - # no /MANIFESTFILE so nothing to do. - return None - if target_desc == CCompiler.EXECUTABLE: - # by default, executables always get the manifest with the - # CRT referenced. - mfid = 1 - else: - # Extension modules try and avoid any manifest if possible. - mfid = 2 - temp_manifest = self._remove_visual_c_ref(temp_manifest) - if temp_manifest is None: - return None - return temp_manifest, mfid - - def _remove_visual_c_ref(self, manifest_file): + def spawn(self, cmd): + old_path = os.getenv('path') try: - # Remove references to the Visual C runtime, so they will - # fall through to the Visual C dependency of Python.exe. - # This way, when installed for a restricted user (e.g. - # runtimes are not in WinSxS folder, but in Python's own - # folder), the runtimes do not need to be in every folder - # with .pyd's. - # Returns either the filename of the modified manifest or - # None if no manifest should be embedded. - manifest_f = open(manifest_file) - try: - manifest_buf = manifest_f.read() - finally: - manifest_f.close() - pattern = re.compile( - r"""|)""", - re.DOTALL) - manifest_buf = re.sub(pattern, "", manifest_buf) - pattern = "\s*" - manifest_buf = re.sub(pattern, "", manifest_buf) - # Now see if any other assemblies are referenced - if not, we - # don't want a manifest embedded. - pattern = re.compile( - r"""|)""", re.DOTALL) - if re.search(pattern, manifest_buf) is None: - return None - - manifest_f = open(manifest_file, 'w') - try: - manifest_f.write(manifest_buf) - return manifest_file - finally: - manifest_f.close() - except OSError: - pass + os.environ['path'] = self._paths + return super().spawn(cmd) + finally: + os.environ['path'] = old_path # -- Miscellaneous methods ----------------------------------------- # These are all used by the 'gen_lib_options() function, in diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py --- a/Lib/distutils/tests/test_msvccompiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -7,88 +7,6 @@ from distutils.tests import support from test.support import run_unittest -# A manifest with the only assembly reference being the msvcrt assembly, so -# should have the assembly completely stripped. Note that although the -# assembly has a reference the assembly is removed - that is -# currently a "feature", not a bug :) -_MANIFEST_WITH_ONLY_MSVC_REFERENCE = """\ - - - - - - - - - - - - - - - - - -""" - -# A manifest with references to assemblies other than msvcrt. When processed, -# this assembly should be returned with just the msvcrt part removed. -_MANIFEST_WITH_MULTIPLE_REFERENCES = """\ - - - - - - - - - - - - - - - - - - - - - - -""" - -_CLEANED_MANIFEST = """\ - - - - - - - - - - - - - - - - - - -""" SKIP_MESSAGE = (None if sys.platform == "win32" else "These tests are only for win32") @@ -114,45 +32,6 @@ finally: _msvccompiler._find_vcvarsall = old_find_vcvarsall - def test_remove_visual_c_ref(self): - from distutils._msvccompiler import MSVCCompiler - tempdir = self.mkdtemp() - manifest = os.path.join(tempdir, 'manifest') - f = open(manifest, 'w') - try: - f.write(_MANIFEST_WITH_MULTIPLE_REFERENCES) - finally: - f.close() - - compiler = MSVCCompiler() - compiler._remove_visual_c_ref(manifest) - - # see what we got - f = open(manifest) - try: - # removing trailing spaces - content = '\n'.join([line.rstrip() for line in f.readlines()]) - finally: - f.close() - - # makes sure the manifest was properly cleaned - self.assertEqual(content, _CLEANED_MANIFEST) - - def test_remove_entire_manifest(self): - from distutils._msvccompiler import MSVCCompiler - tempdir = self.mkdtemp() - manifest = os.path.join(tempdir, 'manifest') - f = open(manifest, 'w') - try: - f.write(_MANIFEST_WITH_ONLY_MSVC_REFERENCE) - finally: - f.close() - - compiler = MSVCCompiler() - got = compiler._remove_visual_c_ref(manifest) - self.assertIsNone(got) - - def test_suite(): return unittest.makeSuite(msvccompilerTestCase) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 7 23:39:38 2015 From: python-checkins at python.org (steve.dower) Date: Fri, 07 Aug 2015 21:39:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Nzk4?= =?utf-8?q?=3A_=5Fmsvccompiler=2Epy_doesn=27t_properly_support_manifests?= Message-ID: <20150807213936.94766.68647@psf.io> https://hg.python.org/cpython/rev/8e966eba2b5e changeset: 97316:8e966eba2b5e branch: 3.5 parent: 97312:b9a0165a3de8 user: Steve Dower date: Wed Aug 05 11:39:19 2015 -0700 summary: Issue #24798: _msvccompiler.py doesn't properly support manifests files: Lib/distutils/_msvccompiler.py | 167 +++------- Lib/distutils/tests/test_msvccompiler.py | 121 ------- Misc/NEWS | 2 + 3 files changed, 52 insertions(+), 238 deletions(-) diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -15,7 +15,6 @@ import os import subprocess -import re from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ CompileError, LibError, LinkError @@ -182,7 +181,8 @@ raise DistutilsPlatformError("Unable to find a compatible " "Visual Studio installation.") - paths = vc_env.get('path', '').split(os.pathsep) + self._paths = vc_env.get('path', '') + paths = self._paths.split(os.pathsep) self.cc = _find_exe("cl.exe", paths) self.linker = _find_exe("link.exe", paths) self.lib = _find_exe("lib.exe", paths) @@ -199,22 +199,40 @@ self.add_library_dir(dir) self.preprocess_options = None + # Use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib + # later to dynamically link to ucrtbase but not vcruntime. self.compile_options = [ - '/nologo', '/Ox', '/MD', '/W3', '/GL', '/DNDEBUG' + '/nologo', '/Ox', '/MT', '/W3', '/GL', '/DNDEBUG' ] self.compile_options_debug = [ - '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' + '/nologo', '/Od', '/MTd', '/Zi', '/W3', '/D_DEBUG' ] - self.ldflags_shared = [ - '/nologo', '/DLL', '/INCREMENTAL:NO', '/LTCG', '/nodefaultlib:libucrt.lib', 'ucrt.lib' + ldflags = [ + '/nologo', '/INCREMENTAL:NO', '/LTCG', '/nodefaultlib:libucrt.lib', 'ucrt.lib', ] - self.ldflags_shared_debug = [ - '/nologo', '/DLL', '/INCREMENTAL:no', '/LTCG', '/DEBUG:FULL', '/nodefaultlib:libucrtd.lib', 'ucrtd.lib' + ldflags_debug = [ + '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL', '/nodefaultlib:libucrtd.lib', 'ucrtd.lib', ] - self.ldflags_static = [ - '/nologo' - ] + + self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1'] + self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1'] + self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO'] + self.ldflags_shared_debug = [*ldflags_debug, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO'] + self.ldflags_static = [*ldflags] + self.ldflags_static_debug = [*ldflags_debug] + + self._ldflags = { + (CCompiler.EXECUTABLE, None): self.ldflags_exe, + (CCompiler.EXECUTABLE, False): self.ldflags_exe, + (CCompiler.EXECUTABLE, True): self.ldflags_exe_debug, + (CCompiler.SHARED_OBJECT, None): self.ldflags_shared, + (CCompiler.SHARED_OBJECT, False): self.ldflags_shared, + (CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug, + (CCompiler.SHARED_LIBRARY, None): self.ldflags_static, + (CCompiler.SHARED_LIBRARY, False): self.ldflags_static, + (CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug, + } self.initialized = True @@ -224,9 +242,12 @@ source_filenames, strip_dir=0, output_dir=''): - ext_map = {ext: self.obj_extension for ext in self.src_extensions} - ext_map.update((ext, self.res_extension) - for ext in self._rc_extensions + self._mc_extensions) + ext_map = { + **{ext: self.obj_extension for ext in self.src_extensions}, + **{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions}, + } + + output_dir = output_dir or '' def make_out_path(p): base, ext = os.path.splitext(p) @@ -237,18 +258,17 @@ if base.startswith((os.path.sep, os.path.altsep)): base = base[1:] try: - return base + ext_map[ext] + # XXX: This may produce absurdly long paths. We should check + # the length of the result and trim base until we fit within + # 260 characters. + return os.path.join(output_dir, base + ext_map[ext]) except LookupError: # Better to raise an exception instead of silently continuing # and later complain about sources and targets having # different lengths raise CompileError("Don't know how to compile {}".format(p)) - output_dir = output_dir or '' - return [ - os.path.join(output_dir, make_out_path(src_name)) - for src_name in source_filenames - ] + return list(map(make_out_path, source_filenames)) def compile(self, sources, @@ -359,6 +379,7 @@ if debug: pass # XXX what goes here? try: + log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args)) self.spawn([self.lib] + lib_args) except DistutilsExecError as msg: raise LibError(msg) @@ -399,14 +420,9 @@ output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): - ldflags = (self.ldflags_shared_debug if debug - else self.ldflags_shared) - if target_desc == CCompiler.EXECUTABLE: - ldflags = ldflags[1:] + ldflags = self._ldflags[target_desc, debug] - export_opts = [] - for sym in (export_symbols or []): - export_opts.append("/EXPORT:" + sym) + export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])] ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) @@ -425,8 +441,6 @@ self.library_filename(dll_name)) ld_args.append ('/IMPLIB:' + implib_file) - self.manifest_setup_ldargs(output_filename, build_temp, ld_args) - if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: @@ -434,101 +448,20 @@ self.mkpath(os.path.dirname(output_filename)) try: + log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) - - # embed the manifest - # XXX - this is somewhat fragile - if mt.exe fails, distutils - # will still consider the DLL up-to-date, but it will not have a - # manifest. Maybe we should link to a temp file? OTOH, that - # implies a build environment error that shouldn't go undetected. - mfinfo = self.manifest_get_embed_info(target_desc, ld_args) - if mfinfo is not None: - mffilename, mfid = mfinfo - out_arg = '-outputresource:{};{}'.format(output_filename, mfid) - try: - self.spawn([self.mt, '-nologo', '-manifest', - mffilename, out_arg]) - except DistutilsExecError as msg: - raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) - def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): - # If we need a manifest at all, an embedded manifest is recommended. - # See MSDN article titled - # "How to: Embed a Manifest Inside a C/C++ Application" - # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) - # Ask the linker to generate the manifest in the temp dir, so - # we can check it, and possibly embed it, later. - temp_manifest = os.path.join( - build_temp, - os.path.basename(output_filename) + ".manifest") - ld_args.append('/MANIFESTFILE:' + temp_manifest) - - def manifest_get_embed_info(self, target_desc, ld_args): - # If a manifest should be embedded, return a tuple of - # (manifest_filename, resource_id). Returns None if no manifest - # should be embedded. See http://bugs.python.org/issue7833 for why - # we want to avoid any manifest for extension modules if we can) - for arg in ld_args: - if arg.startswith("/MANIFESTFILE:"): - temp_manifest = arg.split(":", 1)[1] - break - else: - # no /MANIFESTFILE so nothing to do. - return None - if target_desc == CCompiler.EXECUTABLE: - # by default, executables always get the manifest with the - # CRT referenced. - mfid = 1 - else: - # Extension modules try and avoid any manifest if possible. - mfid = 2 - temp_manifest = self._remove_visual_c_ref(temp_manifest) - if temp_manifest is None: - return None - return temp_manifest, mfid - - def _remove_visual_c_ref(self, manifest_file): + def spawn(self, cmd): + old_path = os.getenv('path') try: - # Remove references to the Visual C runtime, so they will - # fall through to the Visual C dependency of Python.exe. - # This way, when installed for a restricted user (e.g. - # runtimes are not in WinSxS folder, but in Python's own - # folder), the runtimes do not need to be in every folder - # with .pyd's. - # Returns either the filename of the modified manifest or - # None if no manifest should be embedded. - manifest_f = open(manifest_file) - try: - manifest_buf = manifest_f.read() - finally: - manifest_f.close() - pattern = re.compile( - r"""|)""", - re.DOTALL) - manifest_buf = re.sub(pattern, "", manifest_buf) - pattern = "\s*" - manifest_buf = re.sub(pattern, "", manifest_buf) - # Now see if any other assemblies are referenced - if not, we - # don't want a manifest embedded. - pattern = re.compile( - r"""|)""", re.DOTALL) - if re.search(pattern, manifest_buf) is None: - return None - - manifest_f = open(manifest_file, 'w') - try: - manifest_f.write(manifest_buf) - return manifest_file - finally: - manifest_f.close() - except OSError: - pass + os.environ['path'] = self._paths + return super().spawn(cmd) + finally: + os.environ['path'] = old_path # -- Miscellaneous methods ----------------------------------------- # These are all used by the 'gen_lib_options() function, in diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py --- a/Lib/distutils/tests/test_msvccompiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -7,88 +7,6 @@ from distutils.tests import support from test.support import run_unittest -# A manifest with the only assembly reference being the msvcrt assembly, so -# should have the assembly completely stripped. Note that although the -# assembly has a reference the assembly is removed - that is -# currently a "feature", not a bug :) -_MANIFEST_WITH_ONLY_MSVC_REFERENCE = """\ - - - - - - - - - - - - - - - - - -""" - -# A manifest with references to assemblies other than msvcrt. When processed, -# this assembly should be returned with just the msvcrt part removed. -_MANIFEST_WITH_MULTIPLE_REFERENCES = """\ - - - - - - - - - - - - - - - - - - - - - - -""" - -_CLEANED_MANIFEST = """\ - - - - - - - - - - - - - - - - - - -""" SKIP_MESSAGE = (None if sys.platform == "win32" else "These tests are only for win32") @@ -114,45 +32,6 @@ finally: _msvccompiler._find_vcvarsall = old_find_vcvarsall - def test_remove_visual_c_ref(self): - from distutils._msvccompiler import MSVCCompiler - tempdir = self.mkdtemp() - manifest = os.path.join(tempdir, 'manifest') - f = open(manifest, 'w') - try: - f.write(_MANIFEST_WITH_MULTIPLE_REFERENCES) - finally: - f.close() - - compiler = MSVCCompiler() - compiler._remove_visual_c_ref(manifest) - - # see what we got - f = open(manifest) - try: - # removing trailing spaces - content = '\n'.join([line.rstrip() for line in f.readlines()]) - finally: - f.close() - - # makes sure the manifest was properly cleaned - self.assertEqual(content, _CLEANED_MANIFEST) - - def test_remove_entire_manifest(self): - from distutils._msvccompiler import MSVCCompiler - tempdir = self.mkdtemp() - manifest = os.path.join(tempdir, 'manifest') - f = open(manifest, 'w') - try: - f.write(_MANIFEST_WITH_ONLY_MSVC_REFERENCE) - finally: - f.close() - - compiler = MSVCCompiler() - got = compiler._remove_visual_c_ref(manifest) - self.assertIsNone(got) - - def test_suite(): return unittest.makeSuite(msvccompilerTestCase) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #24798: _msvccompiler.py doesn't properly support manifests + - Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 00:50:22 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 07 Aug 2015 22:50:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_typo_in_comment=2E?= Message-ID: <20150807225022.5525.43623@psf.io> https://hg.python.org/cpython/rev/2028c413929b changeset: 97318:2028c413929b user: Eric V. Smith date: Fri Aug 07 18:50:24 2015 -0400 summary: Fix typo in comment. files: Objects/abstract.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2131,7 +2131,7 @@ /* PyObject_Call() must not be called with an exception set, because it may clear it (directly or indirectly) and so the - caller looses its exception */ + caller loses its exception */ assert(!PyErr_Occurred()); call = func->ob_type->tp_call; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 01:49:54 2015 From: python-checkins at python.org (eric.snow) Date: Fri, 07 Aug 2015 23:49:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgZnJvbSAzLjUgKGlzc3VlICMyNDY2Nyku?= Message-ID: <20150807234954.53987.48442@psf.io> https://hg.python.org/cpython/rev/47287c998bb0 changeset: 97320:47287c998bb0 parent: 97318:2028c413929b parent: 97319:adb510322c8f user: Eric Snow date: Fri Aug 07 17:47:35 2015 -0600 summary: Merge from 3.5 (issue #24667). files: Lib/test/test_collections.py | 23 +++++++++++++++++++++++ Misc/NEWS | 2 ++ Objects/odictobject.c | 17 ++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -2106,6 +2106,29 @@ # This should not crash. od.popitem() + def test_issue24667(self): + """ + dict resizes after a certain number of insertion operations, + whether or not there were deletions that freed up slots in the + hash table. During fast node lookup, OrderedDict must correctly + respond to all resizes, even if the current "size" is the same + as the old one. We verify that here by forcing a dict resize + on a sparse odict and then perform an operation that should + trigger an odict resize (e.g. popitem). One key aspect here is + that we will keep the size of the odict the same at each popitem + call. This verifies that we handled the dict resize properly. + """ + OrderedDict = self.module.OrderedDict + + od = OrderedDict() + for c0 in '0123456789ABCDEF': + for c1 in '0123456789ABCDEF': + if len(od) == 4: + # This should not raise a KeyError. + od.popitem(last=False) + key = c0 + c1 + od[key] = key + class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24667: Resize odict in all cases that the underlying dict resizes. + Library ------- diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -483,9 +483,11 @@ PyDictObject od_dict; /* the underlying dict */ _ODictNode *od_first; /* first node in the linked list, if any */ _ODictNode *od_last; /* last node in the linked list, if any */ - /* od_size and od_fast_nodes are managed by _odict_resize() */ - Py_ssize_t od_size; /* hash table that mirrors the dict table */ - _ODictNode **od_fast_nodes; /* managed by _odict_resize() */ + /* od_fast_nodes and od_resize_sentinel are managed by _odict_resize() + * Note that we rely on implementation details of dict for both. */ + _ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */ + Py_uintptr_t od_resize_sentinel; /* changes if odict should be resized */ + size_t od_state; /* incremented whenever the LL changes */ PyObject *od_inst_dict; /* OrderedDict().__dict__ */ PyObject *od_weakreflist; /* holds weakrefs to the odict */ @@ -510,7 +512,6 @@ /* borrowed reference */ #define _odictnode_VALUE(node, od) \ PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node)) -/* If needed we could also have _odictnode_HASH. */ #define _odictnode_PREV(node) (node->prev) #define _odictnode_NEXT(node) (node->next) @@ -520,6 +521,7 @@ #define _odict_FOREACH(od, node) \ for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node)) +#define _odict_FAST_SIZE(od) ((PyDictObject *)od)->ma_keys->dk_size static void _odict_free_fast_nodes(PyODictObject *od) { @@ -573,7 +575,7 @@ /* Replace the old fast nodes table. */ _odict_free_fast_nodes(od); od->od_fast_nodes = fast_nodes; - od->od_size = size; + od->od_resize_sentinel = (Py_uintptr_t)(((PyDictObject *)od)->ma_keys); return 0; } @@ -591,7 +593,7 @@ keys = ((PyDictObject *)od)->ma_keys; /* Ensure od_fast_nodes and dk_entries are in sync. */ - if (keys->dk_size != od->od_size) { + if (od->od_resize_sentinel != (Py_uintptr_t)keys) { int resize_res = _odict_resize(od); if (resize_res < 0) return -1; @@ -656,6 +658,7 @@ _odictnode_NEXT(_odict_LAST(od)) = node; _odict_LAST(od) = node; } + od->od_state++; } @@ -980,7 +983,7 @@ return NULL; res += temp; - res += sizeof(_ODictNode) * od->od_size; /* od_fast_nodes */ + res += sizeof(_ODictNode) * _odict_FAST_SIZE(od); /* od_fast_nodes */ if (!_odict_EMPTY(od)) { res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */ } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 01:49:54 2015 From: python-checkins at python.org (eric.snow) Date: Fri, 07 Aug 2015 23:49:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjY3?= =?utf-8?q?=3A_Resize_odict_in_all_cases_that_the_underlying_dict_resizes?= =?utf-8?q?=2E?= Message-ID: <20150807234954.5531.45570@psf.io> https://hg.python.org/cpython/rev/adb510322c8f changeset: 97319:adb510322c8f branch: 3.5 parent: 97316:8e966eba2b5e user: Eric Snow date: Fri Aug 07 17:45:12 2015 -0600 summary: Issue #24667: Resize odict in all cases that the underlying dict resizes. files: Lib/test/test_collections.py | 23 +++++++++++++++++++++++ Misc/NEWS | 2 ++ Objects/odictobject.c | 17 ++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -2098,6 +2098,29 @@ # This should not crash. od.popitem() + def test_issue24667(self): + """ + dict resizes after a certain number of insertion operations, + whether or not there were deletions that freed up slots in the + hash table. During fast node lookup, OrderedDict must correctly + respond to all resizes, even if the current "size" is the same + as the old one. We verify that here by forcing a dict resize + on a sparse odict and then perform an operation that should + trigger an odict resize (e.g. popitem). One key aspect here is + that we will keep the size of the odict the same at each popitem + call. This verifies that we handled the dict resize properly. + """ + OrderedDict = self.module.OrderedDict + + od = OrderedDict() + for c0 in '0123456789ABCDEF': + for c1 in '0123456789ABCDEF': + if len(od) == 4: + # This should not raise a KeyError. + od.popitem(last=False) + key = c0 + c1 + od[key] = key + class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24667: Resize odict in all cases that the underlying dict resizes. + Library ------- diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -483,9 +483,11 @@ PyDictObject od_dict; /* the underlying dict */ _ODictNode *od_first; /* first node in the linked list, if any */ _ODictNode *od_last; /* last node in the linked list, if any */ - /* od_size and od_fast_nodes are managed by _odict_resize() */ - Py_ssize_t od_size; /* hash table that mirrors the dict table */ - _ODictNode **od_fast_nodes; /* managed by _odict_resize() */ + /* od_fast_nodes and od_resize_sentinel are managed by _odict_resize() + * Note that we rely on implementation details of dict for both. */ + _ODictNode **od_fast_nodes; /* hash table that mirrors the dict table */ + Py_uintptr_t od_resize_sentinel; /* changes if odict should be resized */ + size_t od_state; /* incremented whenever the LL changes */ PyObject *od_inst_dict; /* OrderedDict().__dict__ */ PyObject *od_weakreflist; /* holds weakrefs to the odict */ @@ -510,7 +512,6 @@ /* borrowed reference */ #define _odictnode_VALUE(node, od) \ PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node)) -/* If needed we could also have _odictnode_HASH. */ #define _odictnode_PREV(node) (node->prev) #define _odictnode_NEXT(node) (node->next) @@ -520,6 +521,7 @@ #define _odict_FOREACH(od, node) \ for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node)) +#define _odict_FAST_SIZE(od) ((PyDictObject *)od)->ma_keys->dk_size static void _odict_free_fast_nodes(PyODictObject *od) { @@ -573,7 +575,7 @@ /* Replace the old fast nodes table. */ _odict_free_fast_nodes(od); od->od_fast_nodes = fast_nodes; - od->od_size = size; + od->od_resize_sentinel = (Py_uintptr_t)(((PyDictObject *)od)->ma_keys); return 0; } @@ -591,7 +593,7 @@ keys = ((PyDictObject *)od)->ma_keys; /* Ensure od_fast_nodes and dk_entries are in sync. */ - if (keys->dk_size != od->od_size) { + if (od->od_resize_sentinel != (Py_uintptr_t)keys) { int resize_res = _odict_resize(od); if (resize_res < 0) return -1; @@ -656,6 +658,7 @@ _odictnode_NEXT(_odict_LAST(od)) = node; _odict_LAST(od) = node; } + od->od_state++; } @@ -980,7 +983,7 @@ return NULL; res += temp; - res += sizeof(_ODictNode) * od->od_size; /* od_fast_nodes */ + res += sizeof(_ODictNode) * _odict_FAST_SIZE(od); /* od_fast_nodes */ if (!_odict_EMPTY(od)) { res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */ } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 03:32:59 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 01:32:59 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Initial_version_of_PEP-498=2E?= Message-ID: <20150808013259.29418.61310@psf.io> https://hg.python.org/peps/rev/90863d1b10b4 changeset: 5922:90863d1b10b4 user: Eric V. Smith date: Fri Aug 07 21:33:01 2015 -0400 summary: Initial version of PEP-498. files: pep-0498.txt | 441 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 441 insertions(+), 0 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt new file mode 100644 --- /dev/null +++ b/pep-0498.txt @@ -0,0 +1,441 @@ +PEP: XXX +Title: Literal String Formatting +Version: $Revision$ +Last-Modified: $Date$ +Author: Eric V. Smith +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 01-Aug-2015 +Python-Version: 3.6 +Post-History: 07-Aug-2015 + +Abstract +======== + +Python supports multiple ways to format text strings. These include +%-formatting [#]_, str.format [#]_, and string.Template [#]_. Each of +these methods have their advantages, but in addition have +disadvantages that make them cumbersome to use in practice. This PEP +proposed to add a new string formatting mechanism: Literal String +Formatting. In this PEP, such strings will be refered to as +"f-strings", taken from the leading character used to denote such +strings. + +f-strings provide a way to combine string literals with Python +expressions, using a minimal syntax. It should be noted that an +f-string is really an expression evaluated at run time, not a constant +value. An f-string is a string, prefixed with 'f', that contains +expressions inside braces. The expressions are replaced with their +values. Some examples are:: + + >>> import datetime + >>> name = 'Fred' + >>> age = 50 + >>> anniversary = datetime.date(1991, 10, 12) + >>> f'My name is {name}, my age next year is {age+1}, my anniversary is {anniversary:%A, %B %d, %Y}.' + 'My name is Fred, my age next year is 51, my anniversary is Saturday, October 12, 1991.' + >>> f'He said his name is {name!r}.' + "He said his name is 'Fred'." + +This PEP does not propose to remove or deprecate any of the existing +string formatting mechanisms. + +A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to +support a subset of Python expressions, and did not support the +type-specific string formatting (the __format__ method) which was +introduced with PEP 3101 [#]_. + +Rationale +========= + +This PEP is driven by the desire to have a simpler way to format +strings in Python. The existing ways of formatting are either error +prone, inflexible, or cumbersome. + +%-formatting is limited as to the types it supports. Only ints, strs, +and doubles can be formatted. All other types are either not +supported, or converted to one of these types before formatting. In +addition, there's a well-known trap where a single value is passed:: + + >>> msg = 'disk failure' + >>> 'error: %s' % msg + 'error: disk failure' + +But if msg were ever to be a tuple, the same code would fail:: + + >>> msg = ('disk failure', 32) + >>> 'error: %s' % msg + Traceback (most recent call last): + File "", line 1, in + TypeError: not all arguments converted during string formatting + +To be defensive, the following code should be used:: + + >>> 'error: %s' % (msg,) + "error: ('disk failure', 32)" + +str.format() was added to address some of these problems with +%-formatting. In particular, it uses normal function call syntax (and +therefor supports mutliple parameters) and it is extensible through +the __format__() method on the object being converted to a string. See +PEP-3101 for a detailed rationale. + +However, str.format() is not without its issues. Chief among them are +its verbosity. For example, the text 'value' is repeated here:: + + >>> value = 4 * 20 + >>> 'The value is {value}.'.format(value=value) + 'The value is 80.' + +Even in its simplest form, there is a bit of boilerplate, and the +value that's inserted into the placeholder is sometimes far removed +from where the placeholder is situated:: + + >>> 'The value is {}.'.format(value) + 'The value is 80.' + +With an f-string, this becomes:: + + >>> f'The value is {value}.' + 'The value is 80.' + +f-strings provide a concise, readable way to include expressions +inside strings. + +string.Template has similar shortcomings to str.format(), but also +supports fewer formatting options. In particular, it does not support +__format__. + +No use of globals() or locals() +------------------------------- + +In the discussions on python-dev [#]_, a number of solutions where +presented that used locals() and globals() or their equivalents. All +of these have various problems. Among these are referencing variables +that are not otherwise used in a closure. Consider:: + + >>> def outer(x): + ... def inner(): + ... return 'x={x}'.format_map(locals()) + ... return inner + ... + >>> outer(42)() + Traceback (most recent call last): + File "", line 1, in + File "", line 3, in inner + KeyError: 'x' + +This returns an error because the compiler has not added a reference +to x inside the closure. You need to manually add a reference to x in +order for this to work:: + + >>> def outer(x): + ... def inner(): + ... x + ... return 'x={x}'.format_map(locals()) + ... return inner + ... + >>> outer(42)() + 'x=42' + +Guido stated [#]_ that any solution to better string interpolation +would not use locals() or globals(). + +Specification +============= + +In source code, f-strings are string literals that are prefixed by the +letter 'f'. 'f' may be combined with 'r', in either order, to produce +raw f-string literals. 'f' may not be combined with 'b': there are no +binary f-strings. 'f' may also be combined with 'u', in either order, +although adding 'u' has no effect. + +f-strings are parsed in to literals and expressions. Expressions +appear within curly braces '{' and '}. The parts of the string outside +of braces are literals. The expressions are evaluated, formatted with +the existing __format__ protocol, then the results are concatenated +together with the string literals. While scanning the string for +expressions, any doubled braces '{{' or '}}' are replaced by the +corresponding single brace. Doubled opening braces do not signify the +start of an expression. + +Following the expression, an optionally the type conversion may be +specified. The allowed conversions are '!s' or '!r'. These are +treated the same as in str.format: '!s' calls str() on the expression, +and '!r' calls repr() on the expression. These conversions are applied +before the call to __format__. The only reason to use '!s' is if you +want to specify a format specifier that applies to str, not to the +type of the expression. + +Similar to str.format, optional format specifiers maybe be included +inside the f-string, separated from the expression (or the type +conversion, if specified) by a colon. If a format specifier is not +provied, an empty string is used. + +So, an f-string looks like:: + + f ' { } text ... ' + +The resulting expression's __format__ method is called with the format +specifier. The resulting value is used when building the value of the +f-string. + +Expressions cannot contain ':' or '!' outside of strings or parens, +brackets, or braces. The exception is that the '!=' operator is +special cased. + +Code equivalence +---------------- + +The exact code that is executed when converting expressions to strings +is unspecified by this PEP. However, it is specified that once the +expression is evaluated, the results __format__() method will be +called with the given format specifier. + +For example, this code:: + + f'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi' + +May be evaluated as:: + + ''.join(['abc', expr1.__format__('spec1'), repr(expr2).__format__('spec2'), 'def', str(expr3).__format__(''), 'ghi']) + +Expression evaluation +--------------------- + +The expressions that are extracted from the string are evaluated in +the context where the f-string appeared. This means the expression has +full access to local and global variables. Any valid Python expression +can be used, including function and method calls. + +Because the f-strings are evaluated where the string appears in the +source code, there is no additional expressiveness available with +f-strings. There are also no additional security concerns: you could +have also just written the same expression, not inside of an +f-string:: + + >>> def foo(): + ... return 20 + ... + >>> f'result={foo()}' + 'result=20' + +Is equivalent to:: + + >>> 'result=' + str(foo()) + 'result=20' + +Format specifiers +----------------- + +Format specifiers are not interpreted by the f-string parser. Just as +in str.format(), they are merely passed in to the __format__() method +of the object being formatted. + +Concatenating strings +--------------------- + +Adjacent f-strings and regular strings are concatenated. Regular +strings are concatenated at compile time, and f-strings are +concatenated at run time. For example, the expression:: + + >>> x = 10 + >>> y = 'hi' + >>> 'a' 'b' f'{x}' 'c' f'str<{y:^4}>' 'd' 'e' + +yields the value:: + + 'ab10cstr< hi >de' + +While the exact code that is executed when evaluating this f-string is +not specified, one possible strategy is to evaluate:: + + ''.join(['ab', x.__format__(''), 'c', 'str<', y.__format__('^4'), '>', 'de']) + +Error handling +-------------- + +Either compile time or run time errors can occur when processing +f-strings. Compile time errors are limited to those errors that can be +detected when scanning an f-string. These errors all raise +SyntaxError. + +Unmatched braces:: + + >>> f'x={x' + File "", line 1 + SyntaxError: missing '}' in format string expression + +Invalid expressions:: + + >>> f'x={!x}' + File "", line 1 + !x + ^ + SyntaxError: invalid syntax + +Run time errors occur when evaluating the expressions inside an +f-string. Note that an f-string can be executed multiple times, and +work sometimes and raise an error other times:: + + >>> d = {0:10, 1:20} + >>> for i in range(3): + ... print(f'{i}:{d[i]}') + ... + 0:10 + 1:20 + Traceback (most recent call last): + File "", line 2, in + KeyError: 2 + +Leading whitespace in expressions is skipped +-------------------------------------------- + +Because expressions may begin with a left brace ('{'), there is a +problem when parsing such expressions. For example:: + + >>> f'{{k:v for k, v in [(1, 2), (3, 4)}}' + '{k:v for k, v in [(1, 2), (3, 4)}' + +In this case, the doubled left braces and doubled right braces are +interpreted as single braces, and the string becomes just a normal +string literal. There is no expression evaluation being performed. + +To account for this, whitespace characters at the beginning of an +expression are skipped:: + + >>> f'{ {k:v for k, v in [(1, 2), (3, 4)}}' + '{k:v for k, v in [(1, 2), (3, 4)}' + +Discussion +========== + +Most of the discussions on python-ideas [#]_ focused on a few issues: + + - Whether to allow full Python expressions. + - How to designate f-strings, and how specify the locaton of + expressions in them. + - How to concatenate adjacent strings and f-strings. + +XXX: more on the above issues. + +Differences between f-string and str.format expressions +------------------------------------------------------- + +There is one small difference between the limited expressions allowed +in str.format() and the full expressions allowed inside f-strings. The +difference is in how index lookups are performed. In str.format(), +index values that do not look like numbers are converted to strings:: + + >>> d = {'a': 10, 'b': 20} + >>> 'a={d[a]}'.format(d=d) + 'a=10' + +Notice that the index value is converted to the string "a" when it is +looked up in the dict. + +However, in f-strings, you would need to use a literal for the value +of 'a':: + + >>> f'a={d["a"]}' + 'a=10' + +This difference is required because otherwise you would not be able to +use variables as index values:: + + >>> a = 'b' + >>> f'a={d[a]}' + 'a=20' + +See [#]_ for a further discussion. It was this observation that led to +full Python expressions being supported in f-strings. + +No binary f-strings +------------------- + +For the same reason that we don't support bytes.format(), you may not +combine 'f' with 'b' string literals. The primary problem is that an +object's __format__() method may return Unicode data that is not +compatible with a bytes string. + +!s and !r are redundant +----------------------- + +The !s and !r are not strictly required. Because arbitrary expressions +are allowed inside the f-strings, this code:: + + >>> a = 'some string' + >>> f'{a!r}' + "'some string'" + +Is identical to:: + + >>> f'{repr(a)}' + "'some string'" + +Similarly, !s can be replaced by calls to str(). + +However, !s and !r are supported by this PEP in order to minimize the +differences with str.format(). !s and !r are required in str.format() +because it does not allow the execution of arbitrary expressions. + +Lambdas inside expressions +-------------------------- + +Because lambdas use the ':' character, they cannot appear outside of +parenthesis in an expression. The colon is interpreted as the start of +the format specifier, which means the start of the lambda expression +is seen and is syntactically invalid. As there's no practical use for +a plain lambda in an f-string expression, this is not seen as much of +a limitation. + +Lambdas may be used inside of parens:: + + >>> f'{(lambda x: x*2)(3)}' + '6' + +References +========== + +.. [#] %-formatting + (https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting) + +.. [#] str.format + (https://docs.python.org/3/library/string.html#formatstrings) + +.. [#] string.Template documentation + (https://docs.python.org/3/library/string.html#template-strings) + +.. [#] PEP 215: String Interpolation + (https://www.python.org/dev/peps/pep-0215/) + +.. [#] PEP 3101: Advanced String Formatting + (https://www.python.org/dev/peps/pep-3101/) + +.. [#] Formatting using locals() and globals() + (https://mail.python.org/pipermail/python-ideas/2015-July/034671.html) + +.. [#] Avoid locals() and globals() + (https://mail.python.org/pipermail/python-ideas/2015-July/034701.html) + +.. [#] Start of python-ideas discussion + (https://mail.python.org/pipermail/python-ideas/2015-July/034657.html) + +.. [#] Differences in str.format() and f-string expressions + (https://mail.python.org/pipermail/python-ideas/2015-July/034726.html) + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 03:42:35 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 01:42:35 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_PEP_number=2E?= Message-ID: <20150808014235.1389.14674@psf.io> https://hg.python.org/peps/rev/e30bf84d09b5 changeset: 5923:e30bf84d09b5 user: Eric V. Smith date: Fri Aug 07 21:42:37 2015 -0400 summary: Fixed PEP number. files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -1,4 +1,4 @@ -PEP: XXX +PEP: 498 Title: Literal String Formatting Version: $Revision$ Last-Modified: $Date$ -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 03:49:58 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 01:49:58 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_header_order=2E?= Message-ID: <20150808014958.53977.79275@psf.io> https://hg.python.org/peps/rev/54bd79a7f9df changeset: 5924:54bd79a7f9df user: Eric V. Smith date: Fri Aug 07 21:50:00 2015 -0400 summary: Fixed header order. files: pep-0497.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0497.txt b/pep-0497.txt --- a/pep-0497.txt +++ b/pep-0497.txt @@ -5,8 +5,8 @@ Author: Ed Schofield Status: Draft Type: Process +Content-Type: text/x-rst Created: 04-Aug-2015 -Content-Type: text/x-rst Scope -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 04:18:09 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 02:18:09 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_typo=2E?= Message-ID: <20150808021809.94784.42716@psf.io> https://hg.python.org/peps/rev/0a56f678064d changeset: 5925:0a56f678064d user: Eric V. Smith date: Fri Aug 07 22:13:33 2015 -0400 summary: Fix typo. files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -190,7 +190,7 @@ The exact code that is executed when converting expressions to strings is unspecified by this PEP. However, it is specified that once the -expression is evaluated, the results __format__() method will be +expression is evaluated, the result's __format__() method will be called with the given format specifier. For example, this code:: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 04:25:24 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 02:25:24 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_another_run_time_error_?= =?utf-8?q?example=2E?= Message-ID: <20150808022524.29418.62764@psf.io> https://hg.python.org/peps/rev/b658dd445504 changeset: 5926:b658dd445504 user: Eric V. Smith date: Fri Aug 07 22:25:27 2015 -0400 summary: Added another run time error example. files: pep-0498.txt | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -276,8 +276,8 @@ SyntaxError: invalid syntax Run time errors occur when evaluating the expressions inside an -f-string. Note that an f-string can be executed multiple times, and -work sometimes and raise an error other times:: +f-string. Note that an f-string can be evaluated multiple times, and +work sometimes and raise an error at other times:: >>> d = {0:10, 1:20} >>> for i in range(3): @@ -289,6 +289,17 @@ File "", line 2, in KeyError: 2 +or:: + + >>> for x in (32, 100, 'fifty'): + ... f'x = {x:+3}' + ... + 'x = +32' + 'x = +100' + Traceback (most recent call last): + File "", line 2, in + ValueError: Sign not allowed in string format specifier + Leading whitespace in expressions is skipped -------------------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 05:01:01 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 08 Aug 2015 03:01:01 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Updated_PEP_495=2E?= Message-ID: <20150808030101.29386.72142@psf.io> https://hg.python.org/peps/rev/271749c8805d changeset: 5927:271749c8805d parent: 5921:bc2cb060f261 user: Alexander Belopolsky date: Fri Aug 07 22:58:51 2015 -0400 summary: Updated PEP 495. files: pep-0495.txt | 182 +++++++++++++++++++++++++++++++++++--- 1 files changed, 166 insertions(+), 16 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -72,28 +72,170 @@ The ``replace()`` methods of the ``datetime.time`` and ``datetime.datetime`` classes will get a new keyword-only argument -called ``first`` with the default value ``True``. The value of the -``first`` argument will be used to set the value of the ``first`` -attribute in the returned instance. +called ``first`` with the default value ``True``. It will +becave similarly to the other ``replace()`` arguments: if the ``first`` +argument is specified and given a boolean value, the new instance +returned by ``replace()`` will have its ``first`` attribute set +to that value. In CPython, a non-boolean value of ``first`` will +raise a ``TypeError``, but other implementations may allow the value +``None`` to behave the same as when ``first`` is not given. If the +``first`` argument is not specified, the original value of the ``first`` +attribute is copied to the result. Affected Behaviors ------------------ -The ``timestamp()`` method of ``datetime.datetime`` will return value -advanced by 3600 if ``self`` represents an ambiguous hour and -``first`` is False. +Conversion from naive to aware +.............................. + +The ``astimezone()`` method will now work for naive ``self``. The +system local timezone will be assumed in this case and the ``first`` +flag will be used to determine which local timezone is in effect +in the ambiguous case. + +For example, on a system set to US/Eastern timezone:: + + >>> dt = datetime(2014, 11, 2, 1, 30) + >>> dt.astimezone().strftime('%D %T %Z%z') + '11/02/14 01:30:00 EDT-0400' + >>> dt.replace(first=False).astimezone().strftime('%D %T %Z%z') + '11/02/14 01:30:00 EST-0500' + +Conversion to POSIX seconds from EPOCH +...................................... + +The ``timestamp()`` method of ``datetime.datetime`` will return different +values for ``datetime.datetime`` instances that differ only by the value +of their ``first`` attribute if and only if these instances represent an +ambiguous or a non-existent value. + +When a ``datetime.datetime`` instance ``dt`` represents an ambiguous +(repeated) time, there are two values ``s0`` and ``s1`` such that:: + + datetime.fromtimestamp(s0) == datetime.fromtimestamp(s1) == dt + +In this case, ``dt.timestamp()`` will return the smaller of ``s0`` +and ``s1`` values if ``dt.first == True`` and the larger otherwise. + + +For example, on a system set to US/Eastern timezone:: + + >>> datetime(2014, 11, 2, 1, 30, first=True).timestamp() + 1414906200.0 + >>> datetime(2014, 11, 2, 1, 30, first=False).timestamp() + 1414909800.0 + + +When a ``datetime.datetime`` instance ``dt`` represents an invalid +time, there is no value ``s`` for which:: + + datetime.fromtimestamp(s) == dt + +but we can form two "nice to know" values of ``s`` that differ +by the size of the gap in seconds. One is the value of ``s`` +that would correspond to ``dt`` in a timezone where the UTC offset +is always the same as the offset right before the gap and the +other is the similar value but in a timezone the UTC offset +is always the same as the offset right after the gap. + +The value returned by ``dt.timestamp()`` given the invalid +``dt`` will be the larger of the two "nice to know" values +if ``dt.first == True`` and the larger otherwise. + +For example, on a system set to US/Eastern timezone:: + + >>> datetime(2015, 3, 8, 2, 30, first=True).timestamp() + 1425799800.0 + >>> datetime(2015, 3, 8, 2, 30, first=False).timestamp() + 1425796200.0 + + +Conversion from POSIX seconds from EPOCH +........................................ + The ``fromtimestamp()`` static method of ``datetime.datetime`` will set the ``first`` attribute appropriately in the returned object. +For example, on a system set to US/Eastern timezone:: -Implementations of tzinfo -......................... + >>> datetime.fromtimestamp(1414906200) + datetime.datetime(2014, 11, 2, 1, 30) + >>> datetime.fromtimestamp(1414906200 + 3600) + datetime.datetime(2014, 11, 2, 1, 30, first=False) -Subclasses of ``datetime.tzinfo`` will read the values of ``first`` in -``utcoffset()`` and ``dst()`` methods and set it appropriately in the -instances returned by the ``fromutc()`` method. No change to the -signatures of these methods is proposed. + +Implementations of tzinfo in stdlib +................................... + +No new implementations of ``datetime.tzinfo`` abstract class are +introduced in this PEP. The existing (fixed offset) timezones do +not introduce ambiguous local times and their ``utcoffset()`` +implementation will return the same constant value as they do now +regardless of the value of ``first``. + +New guidelines will be published for implementing concrete timezones +with variable UTC offset. + + +Guidelines for new tzinfo implementations +----------------------------------------- + +Implementors of concrete ``datetime.tzinfo`` subclasses who want to +support variable UTC offsets (due to DST and other causes) must follow +these guidelines. + +New subclasses should override the baseclass ``fromutc()`` method so +that in all cases where two UTC times ``u1`` and ``u2`` (``u1`` <``u2``) +corespond to the same local time ``fromutc(u1)`` will return an instance +with ``first=True`` and ``fromutc(u1)`` will return an instance +with ``first=False``. + +New implementations of ``utcoffset()`` and ``dst()`` methods should +ignore the value of ``first`` unless they are called on the ambiguous +or invalid times. + +On an ambiguous time introduced at the end of DST, the values returned +by ``utcoffset()`` and ``dst()`` methods should be as follows + ++-----------------+----------------+------------------+ +| | first=True | first=False | ++-----------------+----------------+------------------+ +| utcoff() | stdoff + hour | stdoff | ++-----------------+----------------+------------------+ +| dst() | hour | zero | ++-----------------+----------------+------------------+ + +where ``stdoff`` is the standard (non-DST) offset, +``hour = timedelta(hours=1)`` and ``zero = timedelta(0)``. + +On an invalid time introduced at the start of DST, the values returned +by ``utcoffset()`` and ``dst()`` methods should be as follows + + ++-----------------+----------------+------------------+ +| | first=True | first=False | ++-----------------+----------------+------------------+ +| utcoff() | stdoff | stdoff + hour | ++-----------------+----------------+------------------+ +| dst() | zero | hour | ++-----------------+----------------+------------------+ + + +On ambiguous/invalid times introduced by the change in the standard time +offset, the ``dst()`` method should return the same value regardless of +the value of ``first`` and the ``utcoff()`` should return values +according to the following table: + ++-----------------+----------------+-----------------------------+ +| | first=True | first=False | ++-----------------+----------------+-----------------------------+ +| ambiguous | oldoff | newoff = oldoff - delta | ++-----------------+----------------+-----------------------------+ +| invalid | oldoff | newoff = oldoff + delta | ++-----------------+----------------+-----------------------------+ + + Pickle size ----------- @@ -117,7 +259,7 @@ -------------------- The value of "first" will be ignored in all operations except those -that involve conversion between timezones. +that involve conversion between timezones. [#]_ The result of addition (subtraction) of a timedelta to (from) a datetime will always have ``first`` set to ``True`` even if the @@ -125,9 +267,17 @@ (The only methods that will be able to produce non-default value of "first" are ``__new__``, and ``replace()`` methods of the -``datetime.datetime`` and ``datetime.time`` classes ``now()`` and -``fromtimestamp()`` methods of the ``datetime.datetime`` class, and -``fromutc()`` method of some tzinfo implementations.) +``datetime.datetime`` and ``datetime.time`` classes ``now()``, +``astimezone()`` and ``fromtimestamp()`` methods of the +``datetime.datetime`` class, and ``fromutc()`` method of some tzinfo +implementations.) + + +.. [#] As of Python 3.5, ``tzinfo`` is ignored whenever timedelta is + added or subtracted from a ``datetime.datetime`` instance or when + one ``datetime.datetime`` instance is subtracted from another with + the same (even not-None) ``tzinfo``. This may change in the future, + but such changes are outside of the scope of this PEP. Comparison ---------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 05:01:02 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 08 Aug 2015 03:01:02 +0000 Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_merge?= Message-ID: <20150808030101.29396.52949@psf.io> https://hg.python.org/peps/rev/bef97a3bbde9 changeset: 5928:bef97a3bbde9 parent: 5927:271749c8805d parent: 5926:b658dd445504 user: Alexander Belopolsky date: Fri Aug 07 23:00:58 2015 -0400 summary: merge files: pep-0497.txt | 2 +- pep-0498.txt | 452 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 453 insertions(+), 1 deletions(-) diff --git a/pep-0497.txt b/pep-0497.txt --- a/pep-0497.txt +++ b/pep-0497.txt @@ -5,8 +5,8 @@ Author: Ed Schofield Status: Draft Type: Process +Content-Type: text/x-rst Created: 04-Aug-2015 -Content-Type: text/x-rst Scope diff --git a/pep-0498.txt b/pep-0498.txt new file mode 100644 --- /dev/null +++ b/pep-0498.txt @@ -0,0 +1,452 @@ +PEP: 498 +Title: Literal String Formatting +Version: $Revision$ +Last-Modified: $Date$ +Author: Eric V. Smith +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 01-Aug-2015 +Python-Version: 3.6 +Post-History: 07-Aug-2015 + +Abstract +======== + +Python supports multiple ways to format text strings. These include +%-formatting [#]_, str.format [#]_, and string.Template [#]_. Each of +these methods have their advantages, but in addition have +disadvantages that make them cumbersome to use in practice. This PEP +proposed to add a new string formatting mechanism: Literal String +Formatting. In this PEP, such strings will be refered to as +"f-strings", taken from the leading character used to denote such +strings. + +f-strings provide a way to combine string literals with Python +expressions, using a minimal syntax. It should be noted that an +f-string is really an expression evaluated at run time, not a constant +value. An f-string is a string, prefixed with 'f', that contains +expressions inside braces. The expressions are replaced with their +values. Some examples are:: + + >>> import datetime + >>> name = 'Fred' + >>> age = 50 + >>> anniversary = datetime.date(1991, 10, 12) + >>> f'My name is {name}, my age next year is {age+1}, my anniversary is {anniversary:%A, %B %d, %Y}.' + 'My name is Fred, my age next year is 51, my anniversary is Saturday, October 12, 1991.' + >>> f'He said his name is {name!r}.' + "He said his name is 'Fred'." + +This PEP does not propose to remove or deprecate any of the existing +string formatting mechanisms. + +A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to +support a subset of Python expressions, and did not support the +type-specific string formatting (the __format__ method) which was +introduced with PEP 3101 [#]_. + +Rationale +========= + +This PEP is driven by the desire to have a simpler way to format +strings in Python. The existing ways of formatting are either error +prone, inflexible, or cumbersome. + +%-formatting is limited as to the types it supports. Only ints, strs, +and doubles can be formatted. All other types are either not +supported, or converted to one of these types before formatting. In +addition, there's a well-known trap where a single value is passed:: + + >>> msg = 'disk failure' + >>> 'error: %s' % msg + 'error: disk failure' + +But if msg were ever to be a tuple, the same code would fail:: + + >>> msg = ('disk failure', 32) + >>> 'error: %s' % msg + Traceback (most recent call last): + File "", line 1, in + TypeError: not all arguments converted during string formatting + +To be defensive, the following code should be used:: + + >>> 'error: %s' % (msg,) + "error: ('disk failure', 32)" + +str.format() was added to address some of these problems with +%-formatting. In particular, it uses normal function call syntax (and +therefor supports mutliple parameters) and it is extensible through +the __format__() method on the object being converted to a string. See +PEP-3101 for a detailed rationale. + +However, str.format() is not without its issues. Chief among them are +its verbosity. For example, the text 'value' is repeated here:: + + >>> value = 4 * 20 + >>> 'The value is {value}.'.format(value=value) + 'The value is 80.' + +Even in its simplest form, there is a bit of boilerplate, and the +value that's inserted into the placeholder is sometimes far removed +from where the placeholder is situated:: + + >>> 'The value is {}.'.format(value) + 'The value is 80.' + +With an f-string, this becomes:: + + >>> f'The value is {value}.' + 'The value is 80.' + +f-strings provide a concise, readable way to include expressions +inside strings. + +string.Template has similar shortcomings to str.format(), but also +supports fewer formatting options. In particular, it does not support +__format__. + +No use of globals() or locals() +------------------------------- + +In the discussions on python-dev [#]_, a number of solutions where +presented that used locals() and globals() or their equivalents. All +of these have various problems. Among these are referencing variables +that are not otherwise used in a closure. Consider:: + + >>> def outer(x): + ... def inner(): + ... return 'x={x}'.format_map(locals()) + ... return inner + ... + >>> outer(42)() + Traceback (most recent call last): + File "", line 1, in + File "", line 3, in inner + KeyError: 'x' + +This returns an error because the compiler has not added a reference +to x inside the closure. You need to manually add a reference to x in +order for this to work:: + + >>> def outer(x): + ... def inner(): + ... x + ... return 'x={x}'.format_map(locals()) + ... return inner + ... + >>> outer(42)() + 'x=42' + +Guido stated [#]_ that any solution to better string interpolation +would not use locals() or globals(). + +Specification +============= + +In source code, f-strings are string literals that are prefixed by the +letter 'f'. 'f' may be combined with 'r', in either order, to produce +raw f-string literals. 'f' may not be combined with 'b': there are no +binary f-strings. 'f' may also be combined with 'u', in either order, +although adding 'u' has no effect. + +f-strings are parsed in to literals and expressions. Expressions +appear within curly braces '{' and '}. The parts of the string outside +of braces are literals. The expressions are evaluated, formatted with +the existing __format__ protocol, then the results are concatenated +together with the string literals. While scanning the string for +expressions, any doubled braces '{{' or '}}' are replaced by the +corresponding single brace. Doubled opening braces do not signify the +start of an expression. + +Following the expression, an optionally the type conversion may be +specified. The allowed conversions are '!s' or '!r'. These are +treated the same as in str.format: '!s' calls str() on the expression, +and '!r' calls repr() on the expression. These conversions are applied +before the call to __format__. The only reason to use '!s' is if you +want to specify a format specifier that applies to str, not to the +type of the expression. + +Similar to str.format, optional format specifiers maybe be included +inside the f-string, separated from the expression (or the type +conversion, if specified) by a colon. If a format specifier is not +provied, an empty string is used. + +So, an f-string looks like:: + + f ' { } text ... ' + +The resulting expression's __format__ method is called with the format +specifier. The resulting value is used when building the value of the +f-string. + +Expressions cannot contain ':' or '!' outside of strings or parens, +brackets, or braces. The exception is that the '!=' operator is +special cased. + +Code equivalence +---------------- + +The exact code that is executed when converting expressions to strings +is unspecified by this PEP. However, it is specified that once the +expression is evaluated, the result's __format__() method will be +called with the given format specifier. + +For example, this code:: + + f'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi' + +May be evaluated as:: + + ''.join(['abc', expr1.__format__('spec1'), repr(expr2).__format__('spec2'), 'def', str(expr3).__format__(''), 'ghi']) + +Expression evaluation +--------------------- + +The expressions that are extracted from the string are evaluated in +the context where the f-string appeared. This means the expression has +full access to local and global variables. Any valid Python expression +can be used, including function and method calls. + +Because the f-strings are evaluated where the string appears in the +source code, there is no additional expressiveness available with +f-strings. There are also no additional security concerns: you could +have also just written the same expression, not inside of an +f-string:: + + >>> def foo(): + ... return 20 + ... + >>> f'result={foo()}' + 'result=20' + +Is equivalent to:: + + >>> 'result=' + str(foo()) + 'result=20' + +Format specifiers +----------------- + +Format specifiers are not interpreted by the f-string parser. Just as +in str.format(), they are merely passed in to the __format__() method +of the object being formatted. + +Concatenating strings +--------------------- + +Adjacent f-strings and regular strings are concatenated. Regular +strings are concatenated at compile time, and f-strings are +concatenated at run time. For example, the expression:: + + >>> x = 10 + >>> y = 'hi' + >>> 'a' 'b' f'{x}' 'c' f'str<{y:^4}>' 'd' 'e' + +yields the value:: + + 'ab10cstr< hi >de' + +While the exact code that is executed when evaluating this f-string is +not specified, one possible strategy is to evaluate:: + + ''.join(['ab', x.__format__(''), 'c', 'str<', y.__format__('^4'), '>', 'de']) + +Error handling +-------------- + +Either compile time or run time errors can occur when processing +f-strings. Compile time errors are limited to those errors that can be +detected when scanning an f-string. These errors all raise +SyntaxError. + +Unmatched braces:: + + >>> f'x={x' + File "", line 1 + SyntaxError: missing '}' in format string expression + +Invalid expressions:: + + >>> f'x={!x}' + File "", line 1 + !x + ^ + SyntaxError: invalid syntax + +Run time errors occur when evaluating the expressions inside an +f-string. Note that an f-string can be evaluated multiple times, and +work sometimes and raise an error at other times:: + + >>> d = {0:10, 1:20} + >>> for i in range(3): + ... print(f'{i}:{d[i]}') + ... + 0:10 + 1:20 + Traceback (most recent call last): + File "", line 2, in + KeyError: 2 + +or:: + + >>> for x in (32, 100, 'fifty'): + ... f'x = {x:+3}' + ... + 'x = +32' + 'x = +100' + Traceback (most recent call last): + File "", line 2, in + ValueError: Sign not allowed in string format specifier + +Leading whitespace in expressions is skipped +-------------------------------------------- + +Because expressions may begin with a left brace ('{'), there is a +problem when parsing such expressions. For example:: + + >>> f'{{k:v for k, v in [(1, 2), (3, 4)}}' + '{k:v for k, v in [(1, 2), (3, 4)}' + +In this case, the doubled left braces and doubled right braces are +interpreted as single braces, and the string becomes just a normal +string literal. There is no expression evaluation being performed. + +To account for this, whitespace characters at the beginning of an +expression are skipped:: + + >>> f'{ {k:v for k, v in [(1, 2), (3, 4)}}' + '{k:v for k, v in [(1, 2), (3, 4)}' + +Discussion +========== + +Most of the discussions on python-ideas [#]_ focused on a few issues: + + - Whether to allow full Python expressions. + - How to designate f-strings, and how specify the locaton of + expressions in them. + - How to concatenate adjacent strings and f-strings. + +XXX: more on the above issues. + +Differences between f-string and str.format expressions +------------------------------------------------------- + +There is one small difference between the limited expressions allowed +in str.format() and the full expressions allowed inside f-strings. The +difference is in how index lookups are performed. In str.format(), +index values that do not look like numbers are converted to strings:: + + >>> d = {'a': 10, 'b': 20} + >>> 'a={d[a]}'.format(d=d) + 'a=10' + +Notice that the index value is converted to the string "a" when it is +looked up in the dict. + +However, in f-strings, you would need to use a literal for the value +of 'a':: + + >>> f'a={d["a"]}' + 'a=10' + +This difference is required because otherwise you would not be able to +use variables as index values:: + + >>> a = 'b' + >>> f'a={d[a]}' + 'a=20' + +See [#]_ for a further discussion. It was this observation that led to +full Python expressions being supported in f-strings. + +No binary f-strings +------------------- + +For the same reason that we don't support bytes.format(), you may not +combine 'f' with 'b' string literals. The primary problem is that an +object's __format__() method may return Unicode data that is not +compatible with a bytes string. + +!s and !r are redundant +----------------------- + +The !s and !r are not strictly required. Because arbitrary expressions +are allowed inside the f-strings, this code:: + + >>> a = 'some string' + >>> f'{a!r}' + "'some string'" + +Is identical to:: + + >>> f'{repr(a)}' + "'some string'" + +Similarly, !s can be replaced by calls to str(). + +However, !s and !r are supported by this PEP in order to minimize the +differences with str.format(). !s and !r are required in str.format() +because it does not allow the execution of arbitrary expressions. + +Lambdas inside expressions +-------------------------- + +Because lambdas use the ':' character, they cannot appear outside of +parenthesis in an expression. The colon is interpreted as the start of +the format specifier, which means the start of the lambda expression +is seen and is syntactically invalid. As there's no practical use for +a plain lambda in an f-string expression, this is not seen as much of +a limitation. + +Lambdas may be used inside of parens:: + + >>> f'{(lambda x: x*2)(3)}' + '6' + +References +========== + +.. [#] %-formatting + (https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting) + +.. [#] str.format + (https://docs.python.org/3/library/string.html#formatstrings) + +.. [#] string.Template documentation + (https://docs.python.org/3/library/string.html#template-strings) + +.. [#] PEP 215: String Interpolation + (https://www.python.org/dev/peps/pep-0215/) + +.. [#] PEP 3101: Advanced String Formatting + (https://www.python.org/dev/peps/pep-3101/) + +.. [#] Formatting using locals() and globals() + (https://mail.python.org/pipermail/python-ideas/2015-July/034671.html) + +.. [#] Avoid locals() and globals() + (https://mail.python.org/pipermail/python-ideas/2015-July/034701.html) + +.. [#] Start of python-ideas discussion + (https://mail.python.org/pipermail/python-ideas/2015-July/034657.html) + +.. [#] Differences in str.format() and f-string expressions + (https://mail.python.org/pipermail/python-ideas/2015-July/034726.html) + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 06:43:19 2015 From: python-checkins at python.org (chris.angelico) Date: Sat, 08 Aug 2015 04:43:19 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Introduce_PEP_499_from_Camero?= =?utf-8?q?n_Simpson?= Message-ID: <20150808044319.17729.80331@psf.io> https://hg.python.org/peps/rev/462b5e74a564 changeset: 5929:462b5e74a564 user: Chris Angelico date: Sat Aug 08 14:43:09 2015 +1000 summary: Introduce PEP 499 from Cameron Simpson files: pep-0499.txt | 124 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 124 insertions(+), 0 deletions(-) diff --git a/pep-0499.txt b/pep-0499.txt new file mode 100644 --- /dev/null +++ b/pep-0499.txt @@ -0,0 +1,124 @@ +PEP: 499 +Title: ``python -m foo`` should bind ``sys.modules['foo']`` in additon to ``sys.modules['__main__']`` +Version: $Revision$ +Last-Modified: $Date$ +Author: Cameron Simpson +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 07-Aug-2015 +Python-Version: 3.6 + +Abstract +======== + +When a module is used as a main program on the Python command line, +such as by: + + python -m module.name ... + +it is easy to accidentally end up with two independent instances +of the module if that module is again imported within the program. +This PEP proposes a way to fix this problem. + +When a module is invoked via Python's -m option the module is bound +to ``sys.modules['__main__']`` and its ``.__name__`` attribute is set to +``'__main__'``. +This enables the standard "main program" boilerplate code at the +bottom of many modules, such as:: + + if __name__ == '__main__': + sys.exit(main(sys.argv)) + +However, when the above command line invocation is used it is a +natural inference to presume that the module is actually imported +under its official name ``module.name``, +and therefore that if the program again imports that name +then it will obtain the same module instance. + +That actuality is that the module was imported only as ``'__main__'``. +Another import will obtain a distinct module instance, which can +lead to confusing bugs. + + +Proposal +======== + +It is suggested that to fix this situation all that is needed is a +simple change to the way the ``-m`` option is implemented: in addition +to binding the module object to ``sys.modules['__main__']``, it is also +bound to ``sys.modules['module.name']``. + +Nick Coghlan has suggested that this is as simple as modifying the +``runpy`` module's ``_run_module_as_main`` function as follows:: + + main_globals = sys.modules["__main__"].__dict__ + +to instead be:: + + main_module = sys.modules["__main__"] + sys.modules[mod_spec.name] = main_module + main_globals = main_module.__dict__ + + +Considerations and Prerequisites +================================ + +Pickling Modules +---------------- + +Nick has mentioned `issue 19702`_ which proposes (quoted from the issue): + +- runpy will ensure that when __main__ is executed via the import + system, it will also be aliased in sys.modules as __spec__.name +- if __main__.__spec__ is set, pickle will use __spec__.name rather + than __name__ to pickle classes, functions and methods defined in + __main__ +- multiprocessing is updated appropriately to skip creating __mp_main__ + in child processes when __main__.__spec__ is set in the parent + process + +The first point above covers this PEP's specific proposal. + + +Background +========== + +`I tripped over this issue`_ while debugging a main program via a +module which tried to monkey patch a named module, that being the +main program module. Naturally, the monkey patching was ineffective +as it imported the main module by name and thus patched the second +module instance, not the running module instance. + +However, the problem has been around as long as the ``-m`` command +line option and is encountered regularly, if infrequently, by others. + +In addition to `issue 19702`_, the discrepancy around `__main__` +is alluded to in PEP 451 and a similar proposal (predating PEP 451) +is described in PEP 395 under `Fixing dual imports of the main module`_. + + +References +========== + +.. _issue 19702: http://bugs.python.org/issue19702 + +.. _I tripped over this issue: https://mail.python.org/pipermail/python-list/2015-August/694905.html + +.. _Fixing dual imports of the main module: https://www.python.org/dev/peps/pep-0395/#fixing-dual-imports-of-the-main-module + + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 07:26:21 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 05:26:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzQyMTQ6?= =?utf-8?q?_Remove_ineffectual_/pdb=3Anone_option_from_msvc9compiler=2Epy?= Message-ID: <20150808052621.53973.94312@psf.io> https://hg.python.org/cpython/rev/418095f0d711 changeset: 97321:418095f0d711 branch: 2.7 parent: 97301:08e03dfb7dab user: Steve Dower date: Fri Aug 07 19:47:36 2015 -0700 summary: Issue #4214: Remove ineffectual /pdb:none option from msvc9compiler.py files: Lib/distutils/msvc9compiler.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -426,7 +426,7 @@ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] if self.__version >= 7: self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' ] self.ldflags_static = [ '/nologo'] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 07:26:21 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 05:26:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=234214=3A_Remove_ineffectual_/pdb=3Anone_option_from_ms?= =?utf-8?q?vc9compiler=2Epy?= Message-ID: <20150808052621.94778.30506@psf.io> https://hg.python.org/cpython/rev/6a1c2c7b0ee0 changeset: 97323:6a1c2c7b0ee0 branch: 3.5 parent: 97319:adb510322c8f parent: 97322:7c322c296a3b user: Steve Dower date: Fri Aug 07 19:48:26 2015 -0700 summary: Issue #4214: Remove ineffectual /pdb:none option from msvc9compiler.py files: Lib/distutils/msvc9compiler.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -416,7 +416,7 @@ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] if self.__version >= 7: self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' ] self.ldflags_static = [ '/nologo'] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 07:26:21 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 05:26:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzQyMTQ6?= =?utf-8?q?_Remove_ineffectual_/pdb=3Anone_option_from_msvc9compiler=2Epy?= Message-ID: <20150808052621.29404.38640@psf.io> https://hg.python.org/cpython/rev/7c322c296a3b changeset: 97322:7c322c296a3b branch: 3.4 parent: 97311:f5069e6e4229 user: Steve Dower date: Fri Aug 07 19:48:03 2015 -0700 summary: Issue #4214: Remove ineffectual /pdb:none option from msvc9compiler.py files: Lib/distutils/msvc9compiler.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -413,7 +413,7 @@ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] if self.__version >= 7: self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' ] self.ldflags_static = [ '/nologo'] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 07:26:22 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 05:26:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=234214=3A_Remove_ineffectual_/pdb=3Anone_option_f?= =?utf-8?q?rom_msvc9compiler=2Epy?= Message-ID: <20150808052622.41843.67082@psf.io> https://hg.python.org/cpython/rev/b35df92f69e4 changeset: 97324:b35df92f69e4 parent: 97320:47287c998bb0 parent: 97323:6a1c2c7b0ee0 user: Steve Dower date: Fri Aug 07 19:48:43 2015 -0700 summary: Issue #4214: Remove ineffectual /pdb:none option from msvc9compiler.py files: Lib/distutils/msvc9compiler.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -416,7 +416,7 @@ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] if self.__version >= 7: self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' ] self.ldflags_static = [ '/nologo'] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 08:48:34 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 06:48:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Normalize_examples=2E?= Message-ID: <20150808064834.53975.38905@psf.io> https://hg.python.org/peps/rev/0069da558ce6 changeset: 5930:0069da558ce6 parent: 5926:b658dd445504 user: Eric V. Smith date: Sat Aug 08 02:48:16 2015 -0400 summary: Normalize examples. files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -292,7 +292,7 @@ or:: >>> for x in (32, 100, 'fifty'): - ... f'x = {x:+3}' + ... print(f'x = {x:+3}') ... 'x = +32' 'x = +100' -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 08:48:34 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 06:48:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_Merge=2E?= Message-ID: <20150808064834.41823.65527@psf.io> https://hg.python.org/peps/rev/c147dcf14409 changeset: 5931:c147dcf14409 parent: 5930:0069da558ce6 parent: 5929:462b5e74a564 user: Eric V. Smith date: Sat Aug 08 02:48:37 2015 -0400 summary: Merge. files: pep-0495.txt | 182 +++++++++++++++++++++++++++++++++++--- pep-0499.txt | 124 ++++++++++++++++++++++++++ 2 files changed, 290 insertions(+), 16 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -72,28 +72,170 @@ The ``replace()`` methods of the ``datetime.time`` and ``datetime.datetime`` classes will get a new keyword-only argument -called ``first`` with the default value ``True``. The value of the -``first`` argument will be used to set the value of the ``first`` -attribute in the returned instance. +called ``first`` with the default value ``True``. It will +becave similarly to the other ``replace()`` arguments: if the ``first`` +argument is specified and given a boolean value, the new instance +returned by ``replace()`` will have its ``first`` attribute set +to that value. In CPython, a non-boolean value of ``first`` will +raise a ``TypeError``, but other implementations may allow the value +``None`` to behave the same as when ``first`` is not given. If the +``first`` argument is not specified, the original value of the ``first`` +attribute is copied to the result. Affected Behaviors ------------------ -The ``timestamp()`` method of ``datetime.datetime`` will return value -advanced by 3600 if ``self`` represents an ambiguous hour and -``first`` is False. +Conversion from naive to aware +.............................. + +The ``astimezone()`` method will now work for naive ``self``. The +system local timezone will be assumed in this case and the ``first`` +flag will be used to determine which local timezone is in effect +in the ambiguous case. + +For example, on a system set to US/Eastern timezone:: + + >>> dt = datetime(2014, 11, 2, 1, 30) + >>> dt.astimezone().strftime('%D %T %Z%z') + '11/02/14 01:30:00 EDT-0400' + >>> dt.replace(first=False).astimezone().strftime('%D %T %Z%z') + '11/02/14 01:30:00 EST-0500' + +Conversion to POSIX seconds from EPOCH +...................................... + +The ``timestamp()`` method of ``datetime.datetime`` will return different +values for ``datetime.datetime`` instances that differ only by the value +of their ``first`` attribute if and only if these instances represent an +ambiguous or a non-existent value. + +When a ``datetime.datetime`` instance ``dt`` represents an ambiguous +(repeated) time, there are two values ``s0`` and ``s1`` such that:: + + datetime.fromtimestamp(s0) == datetime.fromtimestamp(s1) == dt + +In this case, ``dt.timestamp()`` will return the smaller of ``s0`` +and ``s1`` values if ``dt.first == True`` and the larger otherwise. + + +For example, on a system set to US/Eastern timezone:: + + >>> datetime(2014, 11, 2, 1, 30, first=True).timestamp() + 1414906200.0 + >>> datetime(2014, 11, 2, 1, 30, first=False).timestamp() + 1414909800.0 + + +When a ``datetime.datetime`` instance ``dt`` represents an invalid +time, there is no value ``s`` for which:: + + datetime.fromtimestamp(s) == dt + +but we can form two "nice to know" values of ``s`` that differ +by the size of the gap in seconds. One is the value of ``s`` +that would correspond to ``dt`` in a timezone where the UTC offset +is always the same as the offset right before the gap and the +other is the similar value but in a timezone the UTC offset +is always the same as the offset right after the gap. + +The value returned by ``dt.timestamp()`` given the invalid +``dt`` will be the larger of the two "nice to know" values +if ``dt.first == True`` and the larger otherwise. + +For example, on a system set to US/Eastern timezone:: + + >>> datetime(2015, 3, 8, 2, 30, first=True).timestamp() + 1425799800.0 + >>> datetime(2015, 3, 8, 2, 30, first=False).timestamp() + 1425796200.0 + + +Conversion from POSIX seconds from EPOCH +........................................ + The ``fromtimestamp()`` static method of ``datetime.datetime`` will set the ``first`` attribute appropriately in the returned object. +For example, on a system set to US/Eastern timezone:: -Implementations of tzinfo -......................... + >>> datetime.fromtimestamp(1414906200) + datetime.datetime(2014, 11, 2, 1, 30) + >>> datetime.fromtimestamp(1414906200 + 3600) + datetime.datetime(2014, 11, 2, 1, 30, first=False) -Subclasses of ``datetime.tzinfo`` will read the values of ``first`` in -``utcoffset()`` and ``dst()`` methods and set it appropriately in the -instances returned by the ``fromutc()`` method. No change to the -signatures of these methods is proposed. + +Implementations of tzinfo in stdlib +................................... + +No new implementations of ``datetime.tzinfo`` abstract class are +introduced in this PEP. The existing (fixed offset) timezones do +not introduce ambiguous local times and their ``utcoffset()`` +implementation will return the same constant value as they do now +regardless of the value of ``first``. + +New guidelines will be published for implementing concrete timezones +with variable UTC offset. + + +Guidelines for new tzinfo implementations +----------------------------------------- + +Implementors of concrete ``datetime.tzinfo`` subclasses who want to +support variable UTC offsets (due to DST and other causes) must follow +these guidelines. + +New subclasses should override the baseclass ``fromutc()`` method so +that in all cases where two UTC times ``u1`` and ``u2`` (``u1`` <``u2``) +corespond to the same local time ``fromutc(u1)`` will return an instance +with ``first=True`` and ``fromutc(u1)`` will return an instance +with ``first=False``. + +New implementations of ``utcoffset()`` and ``dst()`` methods should +ignore the value of ``first`` unless they are called on the ambiguous +or invalid times. + +On an ambiguous time introduced at the end of DST, the values returned +by ``utcoffset()`` and ``dst()`` methods should be as follows + ++-----------------+----------------+------------------+ +| | first=True | first=False | ++-----------------+----------------+------------------+ +| utcoff() | stdoff + hour | stdoff | ++-----------------+----------------+------------------+ +| dst() | hour | zero | ++-----------------+----------------+------------------+ + +where ``stdoff`` is the standard (non-DST) offset, +``hour = timedelta(hours=1)`` and ``zero = timedelta(0)``. + +On an invalid time introduced at the start of DST, the values returned +by ``utcoffset()`` and ``dst()`` methods should be as follows + + ++-----------------+----------------+------------------+ +| | first=True | first=False | ++-----------------+----------------+------------------+ +| utcoff() | stdoff | stdoff + hour | ++-----------------+----------------+------------------+ +| dst() | zero | hour | ++-----------------+----------------+------------------+ + + +On ambiguous/invalid times introduced by the change in the standard time +offset, the ``dst()`` method should return the same value regardless of +the value of ``first`` and the ``utcoff()`` should return values +according to the following table: + ++-----------------+----------------+-----------------------------+ +| | first=True | first=False | ++-----------------+----------------+-----------------------------+ +| ambiguous | oldoff | newoff = oldoff - delta | ++-----------------+----------------+-----------------------------+ +| invalid | oldoff | newoff = oldoff + delta | ++-----------------+----------------+-----------------------------+ + + Pickle size ----------- @@ -117,7 +259,7 @@ -------------------- The value of "first" will be ignored in all operations except those -that involve conversion between timezones. +that involve conversion between timezones. [#]_ The result of addition (subtraction) of a timedelta to (from) a datetime will always have ``first`` set to ``True`` even if the @@ -125,9 +267,17 @@ (The only methods that will be able to produce non-default value of "first" are ``__new__``, and ``replace()`` methods of the -``datetime.datetime`` and ``datetime.time`` classes ``now()`` and -``fromtimestamp()`` methods of the ``datetime.datetime`` class, and -``fromutc()`` method of some tzinfo implementations.) +``datetime.datetime`` and ``datetime.time`` classes ``now()``, +``astimezone()`` and ``fromtimestamp()`` methods of the +``datetime.datetime`` class, and ``fromutc()`` method of some tzinfo +implementations.) + + +.. [#] As of Python 3.5, ``tzinfo`` is ignored whenever timedelta is + added or subtracted from a ``datetime.datetime`` instance or when + one ``datetime.datetime`` instance is subtracted from another with + the same (even not-None) ``tzinfo``. This may change in the future, + but such changes are outside of the scope of this PEP. Comparison ---------- diff --git a/pep-0499.txt b/pep-0499.txt new file mode 100644 --- /dev/null +++ b/pep-0499.txt @@ -0,0 +1,124 @@ +PEP: 499 +Title: ``python -m foo`` should bind ``sys.modules['foo']`` in additon to ``sys.modules['__main__']`` +Version: $Revision$ +Last-Modified: $Date$ +Author: Cameron Simpson +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 07-Aug-2015 +Python-Version: 3.6 + +Abstract +======== + +When a module is used as a main program on the Python command line, +such as by: + + python -m module.name ... + +it is easy to accidentally end up with two independent instances +of the module if that module is again imported within the program. +This PEP proposes a way to fix this problem. + +When a module is invoked via Python's -m option the module is bound +to ``sys.modules['__main__']`` and its ``.__name__`` attribute is set to +``'__main__'``. +This enables the standard "main program" boilerplate code at the +bottom of many modules, such as:: + + if __name__ == '__main__': + sys.exit(main(sys.argv)) + +However, when the above command line invocation is used it is a +natural inference to presume that the module is actually imported +under its official name ``module.name``, +and therefore that if the program again imports that name +then it will obtain the same module instance. + +That actuality is that the module was imported only as ``'__main__'``. +Another import will obtain a distinct module instance, which can +lead to confusing bugs. + + +Proposal +======== + +It is suggested that to fix this situation all that is needed is a +simple change to the way the ``-m`` option is implemented: in addition +to binding the module object to ``sys.modules['__main__']``, it is also +bound to ``sys.modules['module.name']``. + +Nick Coghlan has suggested that this is as simple as modifying the +``runpy`` module's ``_run_module_as_main`` function as follows:: + + main_globals = sys.modules["__main__"].__dict__ + +to instead be:: + + main_module = sys.modules["__main__"] + sys.modules[mod_spec.name] = main_module + main_globals = main_module.__dict__ + + +Considerations and Prerequisites +================================ + +Pickling Modules +---------------- + +Nick has mentioned `issue 19702`_ which proposes (quoted from the issue): + +- runpy will ensure that when __main__ is executed via the import + system, it will also be aliased in sys.modules as __spec__.name +- if __main__.__spec__ is set, pickle will use __spec__.name rather + than __name__ to pickle classes, functions and methods defined in + __main__ +- multiprocessing is updated appropriately to skip creating __mp_main__ + in child processes when __main__.__spec__ is set in the parent + process + +The first point above covers this PEP's specific proposal. + + +Background +========== + +`I tripped over this issue`_ while debugging a main program via a +module which tried to monkey patch a named module, that being the +main program module. Naturally, the monkey patching was ineffective +as it imported the main module by name and thus patched the second +module instance, not the running module instance. + +However, the problem has been around as long as the ``-m`` command +line option and is encountered regularly, if infrequently, by others. + +In addition to `issue 19702`_, the discrepancy around `__main__` +is alluded to in PEP 451 and a similar proposal (predating PEP 451) +is described in PEP 395 under `Fixing dual imports of the main module`_. + + +References +========== + +.. _issue 19702: http://bugs.python.org/issue19702 + +.. _I tripped over this issue: https://mail.python.org/pipermail/python-list/2015-August/694905.html + +.. _Fixing dual imports of the main module: https://www.python.org/dev/peps/pep-0395/#fixing-dual-imports-of-the-main-module + + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 11:20:41 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 08 Aug 2015 09:20:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_292_inspired_competitor_t?= =?utf-8?q?o_PEP_498?= Message-ID: <20150808092041.29398.7276@psf.io> https://hg.python.org/peps/rev/73eee55cff6d changeset: 5932:73eee55cff6d user: Nick Coghlan date: Sat Aug 08 19:20:33 2015 +1000 summary: PEP 292 inspired competitor to PEP 498 files: pep-0500.txt | 401 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 401 insertions(+), 0 deletions(-) diff --git a/pep-0500.txt b/pep-0500.txt new file mode 100644 --- /dev/null +++ b/pep-0500.txt @@ -0,0 +1,401 @@ +PEP: 500 +Title: Translation ready string interpolation +Version: $Revision$ +Last-Modified: $Date$ +Author: Nick Coghlan +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 08-Aug-2015 +Python-Version: 3.6 +Post-History: 08-Aug-2015 + +Abstract +======== + +PEP 498 proposes new syntactic support for string interpolation that is +transparent to the compiler, allow name references from the interpolation +operation full access to containing namespaces (as with any other expression), +rather than being limited to explicitly name references. + +This PEP agrees with the basic motivation of PEP 498, but proposes to focus +both the syntax and the implementation on the il8n use case, drawing on the +previous proposals in PEP 292 (which added string.Template) and its predecessor +PEP 215 (which proposed syntactic support, rather than a runtime string +manipulation based approach). The text of this PEP currently assumes that the +reader is familiar with these three previous related proposals. + +The interpolation syntax proposed for this PEP is that of PEP 292, but expanded +to allow arbitrary expressions and format specifiers when using the ``${ref}`` +interpolation syntax. The suggested new string prefix is "i" rather than "f", +with the intended mnemonics being either "interpolated string" or +"il8n string":: + + >>> import datetime + >>> name = 'Jane' + >>> age = 50 + >>> anniversary = datetime.date(1991, 10, 12) + >>> i'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' + 'My name is Jane, my age next year is 51, my anniversary is Saturday, October 12, 1991.' + >>> i'She said her name is ${name!r}.' + "She said her name is 'Jane'." + +This PEP also proposes the introduction of three new builtin functions, +``__interpolate__``, ``__interpolateb__`` and ``__interpolateu__``, which +implement key aspects of the interpolation process, and may be overridden in +accordance with the usual mechanisms for shadowing builtin functions. + +This PEP does not propose to remove or deprecate any of the existing +string formatting mechanisms, as those will remain valuable when formatting +strings that are present directly in the source code of the application. + +The key aim of this PEP that isn't inherited from PEP 498 is to help ensure +that future Python applications are written in a "translation ready" way, where +many interface strings that may need to be translated to allow an application +to be used in multiple languages are flagged as a natural consequence of the +development process, even though they won't be translated by default. + + +Rationale +========= + +PEP 498 makes interpolating values into strings with full access to Python's +lexical namespace semantics simpler, but it does so at the cost of introducing +yet another string interpolation syntax. + +The interpolation syntax devised for PEP 292 is deliberately simple so that the +template strings can be extracted into an il8n message catalog, and passed to +translators who may not themselves be developers. For these use cases, it is +important that the interpolation syntax be as simple as possible, as the +translators are responsible for preserving the substition markers, even as +they translate the surrounding text. The PEP 292 syntax is also a common mesage +catalog syntax already supporting by many commercial software translation +support tools. + +PEP 498 correctly points out that the PEP 292 syntax isn't as flexible as that +introduced for general purpose string formatting in PEP 3101, so this PEP adds +that flexibility to the ``${ref}`` construct in PEP 292, and allows translation +tools the option of rejecting usage of that more advanced syntax at runtime, +rather than categorically rejecting it at compile time. The proposed permitted +expressions inside ``${ref}`` are exactly as defined in PEP 498. + + +Specification +============= + +In source code, i-strings are string literals that are prefixed by the +letter 'i'. The string will be parsed into its components at compile time, +which will then be passed to the new ``__interpolate__`` builtin at runtime. + +The 'i' prefix may be combined with 'b', where the 'i' must appear first, in +which case ``__interpolateb__`` will be called rather than ``__interpolate__``. +Similarly, 'i' may also be combined with 'u' to call ``__interpolateu__`` +rather than ``__interpolate__``. + +The 'i' prefix may also be combined with 'r', with or without 'b' or 'u', to +produce raw i-strings. This disables backslash escape sequences in the string +literal as usual, but has no effect on the runtime interpolation behaviour. + +In all cases, the only permitted location for the 'i' prefix is before all other +prefix characters - it indicates a runtime operation, which is largely +independent of the compile time prefixes (aside from calling different +interpolation functions when combined with 'b' or 'u'). + +i-strings are parsed into literals and expressions. Expressions +appear as either identifiers prefixed with a single "$" character, or +surrounded be a leading '${' and a trailing '}. The parts of the format string +that are not expressions are separated out as string literals. + +While parsing the string, any doubled ``$$`` is replaced with a single ``$`` +and is considered part of the literal text, rather than as introducing an +expression. + +These components are then organised into 3 parallel tuples: + +* parsed format string fields +* expression text +* expression values + +And then passed to the ``__interpolate__`` builtin at runtime:: + + __interpolate__(fields, expressions, values) + +The format string field tuple is inspired by the interface of +``string.Formatter.parse``, and consists of a series of 4-tuples each containing +a leading literal, together with a trailing field number, format specifier, +and conversion specifier. If a given substition field has no leading literal +section, format specifier or conversion specifier, then the corresponding +elements in the tuple are the empty string. If the final part of the string +has no trailing substitution field, then the field number, format specifier +and conversion specifier will all be ``None``. + +The expression text is simply the text of each interpolated expression, as it +appeared in the original string, but without the leading and/or surrounding +expression markers. + +The expression values are the result of evaluating the interpolated expressions +in the exact runtime context where the i-string appears in the source code. + +For the following example i-string:: + + i'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl'``, + +the fields tuple would be:: + + ( + ('abc', 0, 'spec1', ''), + ('', 1, 'spec2' 'r'), + (def', 2, '', 's'), + ('ghi', 3, '', ''), + ('$jkl', None, None, None) + ) + +For the same example, the expression text and value tuples would be:: + + ('expr1', 'expr2', 'expr3', 'ident') # Expression text + (expr1, expr2, expr2, ident) # Expression values + +The fields and expression text tuples can be constant folded at compile time, +while the expression values tuple will always need to be constructed at runtime. + +The default ``__interpolate__`` implementation would have the following +semantics, with field processing being defined in terms of the ``format`` +builtin and ``str.format`` conversion specifiers:: + + _converter = string.Formatter().convert_field + + def __interpolate__(fields, expressions, values): + template_parts = [] + for leading_text, field_num, format_spec, conversion in fields: + template_parts.append(leading_text) + if field_num is not None: + value = values[field_num] + if conversion: + value = _converter(value, conversion) + field_text = format(value, format_spec) + template_parts.append(field_str) + return "".join(template_parts) + +The default ``__interpolateu__`` implementation would be the +``__interpolate__`` builtin. + +The default ``__interpolateb__`` implementation would be defined in terms of +the binary mod-formatting reintroduced in PEP 461:: + + def __interpolateb__(fields, expressions, values): + template_parts = [] + for leading_data, field_num, format_spec, conversion in fields: + template_parts.append(leading_data) + if field_num is not None: + if conversion: + raise ValueError("Conversion specifiers not supported " + "in default binary interpolation") + value = values[field_num] + field_data = ("%" + format_spec) % (value,) + template_parts.append(field_data) + return b"".join(template_parts) + +This definition permits examples like the following:: + + >>> data = 10 + >>> ib'$data' + b'10' + >>> b'${data:%4x}' + b' a' + >>> b'${data:#4x}' + b' 0xa' + >>> b'${data:04X}' + b'000A' + + +Expression evaluation +--------------------- + +The expressions that are extracted from the string are evaluated in +the context where the i-string appeared. This means the expression has +full access to local, nonlocal and global variables. Any valid Python +expression can be used inside ``${}``, including function and method calls. +References without the surrounding braces are limited to looking up single +identifiers. + +Because the i-strings are evaluated where the string appears in the +source code, there is no additional expressiveness available with +i-strings. There are also no additional security concerns: you could +have also just written the same expression, not inside of an +i-string:: + + >>> bar=10 + >>> def foo(data): + ... return data + 20 + ... + >>> i'input=$bar, output=${foo(bar)}' + 'input=10, output=30' + +Is equivalent to:: + + >>> 'input={}, output={}'.format(bar, foo(bar)) + 'input=10, output=30' + +Format specifiers +----------------- + +Format specifiers are not interpreted by the i-string parser - that is +handling at runtime by the called interpolation function. + +Concatenating strings +--------------------- + +As i-strings are shorthand for a runtime builtin function call, implicit +concatenation is a syntax error (similar to attempting implicit concatenation +between bytes and str literals):: + + >>> i"interpolated" "not interpolated" + File "", line 1 + SyntaxError: cannot mix interpolation call with plain literal + +Error handling +-------------- + +Either compile time or run time errors can occur when processing +i-strings. Compile time errors are limited to those errors that can be +detected when parsing an i-string into its component tuples. These errors all +raise SyntaxError. + +Unmatched braces:: + + >>> i'x=${x' + File "", line 1 + SyntaxError: missing '}' in interpolation expression + +Invalid expressions:: + + >>> i'x=${!x}' + File "", line 1 + !x + ^ + SyntaxError: invalid syntax + +Run time errors occur when evaluating the expressions inside an +i-string. See PEP 498 for some examples. + +Different interpolation functions may also impose additional runtime +constraints on acceptable interpolated expressions and other formatting +details, which will be reported as runtime exceptions. + +Leading whitespace in expressions is not skipped +------------------------------------------------ + +Unlike PEP 498, leading whitespace in expressions doesn't need to be skipped - +'$' is not a legal character in Python's syntax, so it can't appear inside +a ``${}`` field except as part of another string, whether interpolated or not. + + +Internationalising interpolated strings +======================================= + +So far, this PEP has said nothing practical about internationalisation - only +formatting text using either str.format or bytes.__mod__ semantics depending +on whether or not a str or bytes object is being interpolated. + +Internationalisation enters the picture by overriding the ``__interpolate__`` +builtin on a module-by-module basis. For example, the following implementation +would delegate interpolation calls to string.Template:: + + def _interpolation_fields_to_template(fields, expressions): + if not all(expr.isidentifier() for expr in expressions): + raise ValueError("Only variable substitions permitted for il8n") + template_parts = [] + for literal_text, field_num, format_spec, conversion in fields: + if format_spec: + raise ValueError("Format specifiers not permitted for il8n") + if conversion: + raise ValueError("Conversion specifiers not permitted for il8n") + template_parts.append(literal_text) + if field_num is not None: + template_parts.append("${" + expressions[field_num] + "}") + return "".join(template_parts) + + def __interpolate__(fields, expressions, values): + catalog_str = _interpolation_fields_to_template(fields, expressions) + translated = _(catalog_str) + values = {k:v for k, v in zip(expressions, values)} + return string.Template(translated).safe_substitute(values) + +If a module were to import that definition of __interpolate__ into the +module namespace, then: + +* Any i"translated & interpolated" strings would be translated +* Any iu"untranslated & interpolated" strings would not be translated +* Any ib"untranslated & interpolated" strings would not be translated +* Any other string and bytes literals would not be translated unless explicitly + passed to the relevant translation machinery at runtime + +This shifts the behaviour from the status quo, where translation support needs +to be added explicitly to each string requiring translation to one where +opting *in* to translation is done on a module by module basis, and +individual interpolated strings can then be opted *out* of translation by +adding the "u" prefix to the string literal in order to call +``__interpolateu__`` instead of ``__interpolate__``. + + +Discussion +========== + +Refer to PEP 498 for additional discussion, as several of the points there +also apply to this PEP. + +Preserving the unmodified format string +--------------------------------------- + +A lot of the complexity in the il8n example is actually in recreating the +original format string from its component parts. It may make sense to preserve +and pass that entire string to the interpolation function, in addition to +the broken down field definitions. + +This approach would also allow translators to more consistently benefit from +the simplicity of the PEP 292 approach to string formatting (in the example +above, surrounding braces are added to the catalog strings even for cases that +don't need them) + + +References +========== + +.. [#] %-formatting + (https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting) + +.. [#] str.format + (https://docs.python.org/3/library/string.html#formatstrings) + +.. [#] string.Template documentation + (https://docs.python.org/3/library/string.html#template-strings) + +.. [#] PEP 215: String Interpolation + (https://www.python.org/dev/peps/pep-0215/) + +.. [#] PEP 292: Simpler String Substitutions + (https://www.python.org/dev/peps/pep-0215/) + +.. [#] PEP 3101: Advanced String Formatting + (https://www.python.org/dev/peps/pep-3101/) + +.. [#] PEP 498: Literal string formatting + (https://www.python.org/dev/peps/pep-0498/) + +.. [#] string.Formatter.parse + (https://docs.python.org/3/library/string.html#string.Formatter.parse) + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 11:29:09 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 08 Aug 2015 09:29:09 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_500=3A_adding_a_missing_?= =?utf-8?b?J25vdCc=?= Message-ID: <20150808092908.111078.15770@psf.io> https://hg.python.org/peps/rev/a065c0c5de7f changeset: 5933:a065c0c5de7f user: Nick Coghlan date: Sat Aug 08 19:28:56 2015 +1000 summary: PEP 500: adding a missing 'not' files: pep-0500.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0500.txt b/pep-0500.txt --- a/pep-0500.txt +++ b/pep-0500.txt @@ -47,7 +47,7 @@ This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms, as those will remain valuable when formatting -strings that are present directly in the source code of the application. +strings that are not present directly in the source code of the application. The key aim of this PEP that isn't inherited from PEP 498 is to help ensure that future Python applications are written in a "translation ready" way, where -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 13:39:40 2015 From: python-checkins at python.org (stefan.krah) Date: Sat, 08 Aug 2015 11:39:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2315944=2E?= Message-ID: <20150808113939.17729.42842@psf.io> https://hg.python.org/cpython/rev/c7c4b8411037 changeset: 97326:c7c4b8411037 parent: 97324:b35df92f69e4 parent: 97325:e33f2b8b937f user: Stefan Krah date: Sat Aug 08 13:38:59 2015 +0200 summary: Merge #15944. files: Doc/library/stdtypes.rst | 5 +++- Lib/test/test_buffer.py | 29 +++++++++++++++++++++++- Lib/test/test_memoryview.py | 21 ++++++++++++++++++ Misc/NEWS | 3 ++ Objects/memoryobject.c | 10 +------ 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3564,7 +3564,7 @@ the buffer itself is not copied. Supported casts are 1D -> C-contiguous and C-contiguous -> 1D. - Both formats are restricted to single element native formats in + The destination format is restricted to a single element native format in :mod:`struct` syntax. One of the formats must be a byte format ('B', 'b' or 'c'). The byte length of the result must be the same as the original length. @@ -3645,6 +3645,9 @@ .. versionadded:: 3.3 + .. versionchanged:: 3.5 + The source format is no longer restricted when casting to a byte view. + There are also several readonly attributes available: .. attribute:: obj diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -2559,8 +2559,7 @@ ex = ndarray(sitems, shape=[1], format=sfmt) msrc = memoryview(ex) for dfmt, _, _ in iter_format(1): - if (not is_memoryview_format(sfmt) or - not is_memoryview_format(dfmt)): + if not is_memoryview_format(dfmt): self.assertRaises(ValueError, msrc.cast, dfmt, [32//dsize]) else: @@ -2773,6 +2772,32 @@ ndim=ndim, shape=shape, strides=strides, lst=lst, cast=True) + if ctypes: + # format: "T{>l:x:>d:y:}" + class BEPoint(ctypes.BigEndianStructure): + _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)] + point = BEPoint(100, 200.1) + m1 = memoryview(point) + m2 = m1.cast('B') + self.assertEqual(m2.obj, point) + self.assertEqual(m2.itemsize, 1) + self.assertEqual(m2.readonly, 0) + self.assertEqual(m2.ndim, 1) + self.assertEqual(m2.shape, (m2.nbytes,)) + self.assertEqual(m2.strides, (1,)) + self.assertEqual(m2.suboffsets, ()) + + x = ctypes.c_double(1.2) + m1 = memoryview(x) + m2 = m1.cast('c') + self.assertEqual(m2.obj, x) + self.assertEqual(m2.itemsize, 1) + self.assertEqual(m2.readonly, 0) + self.assertEqual(m2.ndim, 1) + self.assertEqual(m2.shape, (m2.nbytes,)) + self.assertEqual(m2.strides, (1,)) + self.assertEqual(m2.suboffsets, ()) + def test_memoryview_tolist(self): # Most tolist() tests are in self.verify() etc. diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -492,5 +492,26 @@ pass +class OtherTest(unittest.TestCase): + def test_ctypes_cast(self): + # Issue 15944: Allow all source formats when casting to bytes. + ctypes = test.support.import_module("ctypes") + p6 = bytes(ctypes.c_double(0.6)) + + d = ctypes.c_double() + m = memoryview(d).cast("B") + m[:2] = p6[:2] + m[2:] = p6[2:] + self.assertEqual(d.value, 0.6) + + for format in "Bbc": + with self.subTest(format): + d = ctypes.c_double() + m = memoryview(d).cast(format) + m[:2] = memoryview(p6).cast(format)[:2] + m[2:] = memoryview(p6).cast(format)[2:] + self.assertEqual(d.value, 0.6) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -117,6 +117,9 @@ - Issue #24687: Plug refleak on SyntaxError in function parameters annotations. +- Issue #15944: memoryview: Allow arbitrary formats when casting to bytes. + Patch by Martin Panter. + Library ------- diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -1197,13 +1197,6 @@ assert(view->strides == mv->ob_array + view->ndim); assert(view->suboffsets == mv->ob_array + 2*view->ndim); - if (get_native_fmtchar(&srcchar, view->format) < 0) { - PyErr_SetString(PyExc_ValueError, - "memoryview: source format must be a native single character " - "format prefixed with an optional '@'"); - return ret; - } - asciifmt = PyUnicode_AsASCIIString(format); if (asciifmt == NULL) return ret; @@ -1216,7 +1209,8 @@ goto out; } - if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) { + if ((get_native_fmtchar(&srcchar, view->format) < 0 || + !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) { PyErr_SetString(PyExc_TypeError, "memoryview: cannot cast between two non-byte formats"); goto out; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 13:39:40 2015 From: python-checkins at python.org (stefan.krah) Date: Sat, 08 Aug 2015 11:39:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzE1OTQ0?= =?utf-8?q?=3A_memoryview=3A_Allow_arbitrary_formats_when_casting_to_bytes?= =?utf-8?q?=2E?= Message-ID: <20150808113939.29410.28550@psf.io> https://hg.python.org/cpython/rev/e33f2b8b937f changeset: 97325:e33f2b8b937f branch: 3.5 parent: 97323:6a1c2c7b0ee0 user: Stefan Krah date: Sat Aug 08 13:38:10 2015 +0200 summary: Issue #15944: memoryview: Allow arbitrary formats when casting to bytes. Original patch by Martin Panter. files: Doc/library/stdtypes.rst | 5 +++- Lib/test/test_buffer.py | 29 +++++++++++++++++++++++- Lib/test/test_memoryview.py | 21 ++++++++++++++++++ Misc/NEWS | 3 ++ Objects/memoryobject.c | 10 +------ 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3564,7 +3564,7 @@ the buffer itself is not copied. Supported casts are 1D -> C-contiguous and C-contiguous -> 1D. - Both formats are restricted to single element native formats in + The destination format is restricted to a single element native format in :mod:`struct` syntax. One of the formats must be a byte format ('B', 'b' or 'c'). The byte length of the result must be the same as the original length. @@ -3645,6 +3645,9 @@ .. versionadded:: 3.3 + .. versionchanged:: 3.5 + The source format is no longer restricted when casting to a byte view. + There are also several readonly attributes available: .. attribute:: obj diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -2559,8 +2559,7 @@ ex = ndarray(sitems, shape=[1], format=sfmt) msrc = memoryview(ex) for dfmt, _, _ in iter_format(1): - if (not is_memoryview_format(sfmt) or - not is_memoryview_format(dfmt)): + if not is_memoryview_format(dfmt): self.assertRaises(ValueError, msrc.cast, dfmt, [32//dsize]) else: @@ -2773,6 +2772,32 @@ ndim=ndim, shape=shape, strides=strides, lst=lst, cast=True) + if ctypes: + # format: "T{>l:x:>d:y:}" + class BEPoint(ctypes.BigEndianStructure): + _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)] + point = BEPoint(100, 200.1) + m1 = memoryview(point) + m2 = m1.cast('B') + self.assertEqual(m2.obj, point) + self.assertEqual(m2.itemsize, 1) + self.assertEqual(m2.readonly, 0) + self.assertEqual(m2.ndim, 1) + self.assertEqual(m2.shape, (m2.nbytes,)) + self.assertEqual(m2.strides, (1,)) + self.assertEqual(m2.suboffsets, ()) + + x = ctypes.c_double(1.2) + m1 = memoryview(x) + m2 = m1.cast('c') + self.assertEqual(m2.obj, x) + self.assertEqual(m2.itemsize, 1) + self.assertEqual(m2.readonly, 0) + self.assertEqual(m2.ndim, 1) + self.assertEqual(m2.shape, (m2.nbytes,)) + self.assertEqual(m2.strides, (1,)) + self.assertEqual(m2.suboffsets, ()) + def test_memoryview_tolist(self): # Most tolist() tests are in self.verify() etc. diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -492,5 +492,26 @@ pass +class OtherTest(unittest.TestCase): + def test_ctypes_cast(self): + # Issue 15944: Allow all source formats when casting to bytes. + ctypes = test.support.import_module("ctypes") + p6 = bytes(ctypes.c_double(0.6)) + + d = ctypes.c_double() + m = memoryview(d).cast("B") + m[:2] = p6[:2] + m[2:] = p6[2:] + self.assertEqual(d.value, 0.6) + + for format in "Bbc": + with self.subTest(format): + d = ctypes.c_double() + m = memoryview(d).cast(format) + m[:2] = memoryview(p6).cast(format)[:2] + m[2:] = memoryview(p6).cast(format)[2:] + self.assertEqual(d.value, 0.6) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -98,6 +98,9 @@ - Issue #24687: Plug refleak on SyntaxError in function parameters annotations. +- Issue #15944: memoryview: Allow arbitrary formats when casting to bytes. + Patch by Martin Panter. + Library ------- diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -1197,13 +1197,6 @@ assert(view->strides == mv->ob_array + view->ndim); assert(view->suboffsets == mv->ob_array + 2*view->ndim); - if (get_native_fmtchar(&srcchar, view->format) < 0) { - PyErr_SetString(PyExc_ValueError, - "memoryview: source format must be a native single character " - "format prefixed with an optional '@'"); - return ret; - } - asciifmt = PyUnicode_AsASCIIString(format); if (asciifmt == NULL) return ret; @@ -1216,7 +1209,8 @@ goto out; } - if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) { + if ((get_native_fmtchar(&srcchar, view->format) < 0 || + !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) { PyErr_SetString(PyExc_TypeError, "memoryview: cannot cast between two non-byte formats"); goto out; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 14:34:48 2015 From: python-checkins at python.org (stefan.krah) Date: Sat, 08 Aug 2015 12:34:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2323756=2E?= Message-ID: <20150808123448.17739.54099@psf.io> https://hg.python.org/cpython/rev/c59b2c4f4cac changeset: 97328:c59b2c4f4cac parent: 97326:c7c4b8411037 parent: 97327:d1ef54751412 user: Stefan Krah date: Sat Aug 08 14:34:17 2015 +0200 summary: Merge #23756. files: Doc/c-api/buffer.rst | 15 +++++++++------ Doc/c-api/memoryview.rst | 2 +- Doc/glossary.rst | 18 ++++++++++++++++-- Doc/library/stdtypes.rst | 8 ++++---- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -96,8 +96,8 @@ block of the exporter. For example, with negative :c:member:`~Py_buffer.strides` the value may point to the end of the memory block. - For contiguous arrays, the value points to the beginning of the memory - block. + For :term:`contiguous` arrays, the value points to the beginning of + the memory block. .. c:member:: void \*obj @@ -281,11 +281,14 @@ +-----------------------------+-------+---------+------------+ +.. index:: contiguous, C-contiguous, Fortran contiguous + contiguity requests ~~~~~~~~~~~~~~~~~~~ -C or Fortran contiguity can be explicitly requested, with and without stride -information. Without stride information, the buffer must be C-contiguous. +C or Fortran :term:`contiguity ` can be explicitly requested, +with and without stride information. Without stride information, the buffer +must be C-contiguous. .. tabularcolumns:: |p{0.35\linewidth}|l|l|l|l| @@ -466,13 +469,13 @@ .. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order) Return 1 if the memory defined by the *view* is C-style (*order* is - ``'C'``) or Fortran-style (*order* is ``'F'``) contiguous or either one + ``'C'``) or Fortran-style (*order* is ``'F'``) :term:`contiguous` or either one (*order* is ``'A'``). Return 0 otherwise. .. c:function:: void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char order) - Fill the *strides* array with byte-strides of a contiguous (C-style if + Fill the *strides* array with byte-strides of a :term:`contiguous` (C-style if *order* is ``'C'`` or Fortran-style if *order* is ``'F'``) array of the given shape with the given number of bytes per element. diff --git a/Doc/c-api/memoryview.rst b/Doc/c-api/memoryview.rst --- a/Doc/c-api/memoryview.rst +++ b/Doc/c-api/memoryview.rst @@ -35,7 +35,7 @@ .. c:function:: PyObject *PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order) - Create a memoryview object to a contiguous chunk of memory (in either + Create a memoryview object to a :term:`contiguous` chunk of memory (in either 'C' or 'F'ortran *order*) from an object that defines the buffer interface. If memory is contiguous, the memoryview object points to the original memory. Otherwise, a copy is made and the memoryview points to a diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -109,8 +109,10 @@ A :term:`text file` reads and writes :class:`str` objects. bytes-like object - An object that supports the :ref:`bufferobjects`, like :class:`bytes`, - :class:`bytearray` or :class:`memoryview`. Bytes-like objects can + An object that supports the :ref:`bufferobjects` and can + export a C-:term:`contiguous` buffer. This includes all :class:`bytes`, + :class:`bytearray`, and :class:`array.array` objects, as well as many + common :class:`memoryview` objects. Bytes-like objects can be used for various operations that work with binary data; these include compression, saving to a binary file, and sending over a socket. @@ -169,6 +171,18 @@ statement by defining :meth:`__enter__` and :meth:`__exit__` methods. See :pep:`343`. + contiguous + .. index:: C-contiguous, Fortran contiguous + + A buffer is considered contiguous exactly if it is either + *C-contiguous* or *Fortran contiguous*. Zero-dimensional buffers are + C and Fortran contiguous. In one-dimensional arrays, the items + must be layed out in memory next to each other, in order of + increasing indexes starting from zero. In multidimensional + C-contiguous arrays, the last index varies the fastest when + visiting items in order of memory address. However, in + Fortran contiguous arrays, the first index varies the fastest. + coroutine Coroutines is a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines can be diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3561,7 +3561,7 @@ Cast a memoryview to a new format or shape. *shape* defaults to ``[byte_length//new_itemsize]``, which means that the result view will be one-dimensional. The return value is a new memoryview, but - the buffer itself is not copied. Supported casts are 1D -> C-contiguous + the buffer itself is not copied. Supported casts are 1D -> C-:term:`contiguous` and C-contiguous -> 1D. The destination format is restricted to a single element native format in @@ -3752,19 +3752,19 @@ .. attribute:: c_contiguous - A bool indicating whether the memory is C-contiguous. + A bool indicating whether the memory is C-:term:`contiguous`. .. versionadded:: 3.3 .. attribute:: f_contiguous - A bool indicating whether the memory is Fortran contiguous. + A bool indicating whether the memory is Fortran :term:`contiguous`. .. versionadded:: 3.3 .. attribute:: contiguous - A bool indicating whether the memory is contiguous. + A bool indicating whether the memory is :term:`contiguous`. .. versionadded:: 3.3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 14:34:48 2015 From: python-checkins at python.org (stefan.krah) Date: Sat, 08 Aug 2015 12:34:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzNzU2?= =?utf-8?q?=3A_Clarify_the_terms_=22contiguous=22_and_=22bytes-like_object?= =?utf-8?b?Ii4=?= Message-ID: <20150808123448.41835.74021@psf.io> https://hg.python.org/cpython/rev/d1ef54751412 changeset: 97327:d1ef54751412 branch: 3.5 parent: 97325:e33f2b8b937f user: Stefan Krah date: Sat Aug 08 14:33:28 2015 +0200 summary: Issue #23756: Clarify the terms "contiguous" and "bytes-like object". Patch by Martin Panter. files: Doc/c-api/buffer.rst | 15 +++++++++------ Doc/c-api/memoryview.rst | 2 +- Doc/glossary.rst | 18 ++++++++++++++++-- Doc/library/stdtypes.rst | 8 ++++---- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -96,8 +96,8 @@ block of the exporter. For example, with negative :c:member:`~Py_buffer.strides` the value may point to the end of the memory block. - For contiguous arrays, the value points to the beginning of the memory - block. + For :term:`contiguous` arrays, the value points to the beginning of + the memory block. .. c:member:: void \*obj @@ -281,11 +281,14 @@ +-----------------------------+-------+---------+------------+ +.. index:: contiguous, C-contiguous, Fortran contiguous + contiguity requests ~~~~~~~~~~~~~~~~~~~ -C or Fortran contiguity can be explicitly requested, with and without stride -information. Without stride information, the buffer must be C-contiguous. +C or Fortran :term:`contiguity ` can be explicitly requested, +with and without stride information. Without stride information, the buffer +must be C-contiguous. .. tabularcolumns:: |p{0.35\linewidth}|l|l|l|l| @@ -466,13 +469,13 @@ .. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order) Return 1 if the memory defined by the *view* is C-style (*order* is - ``'C'``) or Fortran-style (*order* is ``'F'``) contiguous or either one + ``'C'``) or Fortran-style (*order* is ``'F'``) :term:`contiguous` or either one (*order* is ``'A'``). Return 0 otherwise. .. c:function:: void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char order) - Fill the *strides* array with byte-strides of a contiguous (C-style if + Fill the *strides* array with byte-strides of a :term:`contiguous` (C-style if *order* is ``'C'`` or Fortran-style if *order* is ``'F'``) array of the given shape with the given number of bytes per element. diff --git a/Doc/c-api/memoryview.rst b/Doc/c-api/memoryview.rst --- a/Doc/c-api/memoryview.rst +++ b/Doc/c-api/memoryview.rst @@ -35,7 +35,7 @@ .. c:function:: PyObject *PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order) - Create a memoryview object to a contiguous chunk of memory (in either + Create a memoryview object to a :term:`contiguous` chunk of memory (in either 'C' or 'F'ortran *order*) from an object that defines the buffer interface. If memory is contiguous, the memoryview object points to the original memory. Otherwise, a copy is made and the memoryview points to a diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -109,8 +109,10 @@ A :term:`text file` reads and writes :class:`str` objects. bytes-like object - An object that supports the :ref:`bufferobjects`, like :class:`bytes`, - :class:`bytearray` or :class:`memoryview`. Bytes-like objects can + An object that supports the :ref:`bufferobjects` and can + export a C-:term:`contiguous` buffer. This includes all :class:`bytes`, + :class:`bytearray`, and :class:`array.array` objects, as well as many + common :class:`memoryview` objects. Bytes-like objects can be used for various operations that work with binary data; these include compression, saving to a binary file, and sending over a socket. @@ -169,6 +171,18 @@ statement by defining :meth:`__enter__` and :meth:`__exit__` methods. See :pep:`343`. + contiguous + .. index:: C-contiguous, Fortran contiguous + + A buffer is considered contiguous exactly if it is either + *C-contiguous* or *Fortran contiguous*. Zero-dimensional buffers are + C and Fortran contiguous. In one-dimensional arrays, the items + must be layed out in memory next to each other, in order of + increasing indexes starting from zero. In multidimensional + C-contiguous arrays, the last index varies the fastest when + visiting items in order of memory address. However, in + Fortran contiguous arrays, the first index varies the fastest. + coroutine Coroutines is a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines can be diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3561,7 +3561,7 @@ Cast a memoryview to a new format or shape. *shape* defaults to ``[byte_length//new_itemsize]``, which means that the result view will be one-dimensional. The return value is a new memoryview, but - the buffer itself is not copied. Supported casts are 1D -> C-contiguous + the buffer itself is not copied. Supported casts are 1D -> C-:term:`contiguous` and C-contiguous -> 1D. The destination format is restricted to a single element native format in @@ -3752,19 +3752,19 @@ .. attribute:: c_contiguous - A bool indicating whether the memory is C-contiguous. + A bool indicating whether the memory is C-:term:`contiguous`. .. versionadded:: 3.3 .. attribute:: f_contiguous - A bool indicating whether the memory is Fortran contiguous. + A bool indicating whether the memory is Fortran :term:`contiguous`. .. versionadded:: 3.3 .. attribute:: contiguous - A bool indicating whether the memory is contiguous. + A bool indicating whether the memory is :term:`contiguous`. .. versionadded:: 3.3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 16:07:37 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 08 Aug 2015 14:07:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_a_placeholder_to_remind_m?= =?utf-8?q?e_to_insert_my_research_on_what_other_languages?= Message-ID: <20150808140736.29410.59498@psf.io> https://hg.python.org/peps/rev/b3e3a88f1bd0 changeset: 5934:b3e3a88f1bd0 user: Eric V. Smith date: Sat Aug 08 10:07:40 2015 -0400 summary: Add a placeholder to remind me to insert my research on what other languages support. files: pep-0498.txt | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -331,6 +331,11 @@ XXX: more on the above issues. +Similar support in other languages +---------------------------------- + +XXX: Placeholder. + Differences between f-string and str.format expressions ------------------------------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 16:52:44 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 08 Aug 2015 14:52:44 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_474_for_my_change_?= =?utf-8?q?in_role?= Message-ID: <20150808145244.17719.71758@psf.io> https://hg.python.org/peps/rev/817c0e251e34 changeset: 5935:817c0e251e34 user: Nick Coghlan date: Sun Aug 09 00:52:37 2015 +1000 summary: Update PEP 474 for my change in role files: pep-0474.txt | 97 ++++++++++++--------------------------- 1 files changed, 30 insertions(+), 67 deletions(-) diff --git a/pep-0474.txt b/pep-0474.txt --- a/pep-0474.txt +++ b/pep-0474.txt @@ -76,21 +76,23 @@ * MUST support online editing for simple changes * MUST be backed by an active development organisation (community or commercial) +* MUST support self-hosting of the master repository on PSF infrastructure + without ongoing fees Additional recommended requirements that are satisfied by this proposal, but may be negotiable if a sufficiently compelling alternative is presented: -* SHOULD support self-hosting on PSF infrastructure without ongoing fees * SHOULD be a fully open source application written in Python * SHOULD support Mercurial (for consistency with existing tooling) * SHOULD support Git (to provide that option to users that prefer it) * SHOULD allow users of git and Mercurial clients to transparently collaborate on the same repository +* SHOULD allow users of GitHub and BitBucket to submit proposed changes using + the standard pull request workflows offered by those tools * SHOULD be open to customisation to meet the needs of CPython core development, including providing a potential path forward for the proposed migration to a core reviewer model in PEP 462 - The preference for self-hosting without ongoing fees rules out the free-as-in-beer providers like GitHub and BitBucket, in addition to the various proprietary source code management offerings. @@ -203,76 +205,32 @@ python.org web site. -Funding of development ----------------------- - -As several aspects of this proposal and PEP 462 align with various workflow -improvements under consideration for Red Hat's -`Beaker `__ open source hardware integration -testing system and other work-related projects, I have arranged to be able -to devote ~1 day a week to working on CPython infrastructure projects. - -Together with Rackspace's existing contributions to maintaining the -pypi.python.org infrastructure, I personally believe this arrangement is -indicative of a more general recognition amongst CPython redistributors and -major users of the merit in helping to sustain upstream infrastructure -through direct contributions of developer time, rather than expecting -volunteer contributors to maintain that infrastructure entirely in their -spare time or funding it indirectly through the PSF (with the additional -management overhead that would entail). I consider this a positive trend, and -one that I will continue to encourage as best I can. - - Personal Motivation =================== -As of March 2015, having moved from Boeing Defence Australia (where I had -worked since September 1998) to Red Hat back in June 2011 , I now work for -Red Hat as a software development workflow designer and process architect, -focusing on the open source cross-platform -`Atomic Developer Bundle `__, -which is part of the tooling ecosystem for the -`Project Atomic `__ container hosting platform. -Two of the key pieces of that bundle will be familiar to many readers: -Docker for container management, and Vagrant for cross-platform local -development VM management. +As of July 2015, I now work for Red Hat as a software development workflow +designer and process architect, focusing on the upstream developer experience +in Fedora. Two of the key pieces of that experience will be familiar to many +web service developers: Docker for local container management, and Vagrant for +cross-platform local development VM management. Spending time applying these +technologies in multiple upstream contexts helps provide additional insight +into what works well and what still needs further improvement to provide a good +software development experience that is well integrated on Fedora, but also +readily available on other Linux distributions, Windows, Mac OS X. -However, rather than being a developer for the downstream Red Hat Enterprise -Linux Container Development Kit, I work with the development teams for a -range of Red Hat's internal services, encouraging the standardisation of -internal development tooling and processes on the Atomic Developer Bundle, -contributing upstream as required to ensure it meets our needs and -expectations. As with other Red Hat community web service development -projects like `PatternFly `__, this approach -helps enable standardisation across internal services, community projects, -and commercial products, while still leaving individual development teams -with significant scope to appropriately prioritise their process improvement -efforts by focusing on the limitations currently causing the most -difficulties for them and their users. +In relation to code review workflows in particular, the primary code review +workflow management tools I've used in my career are +Gerrit (for multi-step code review with fine-grained access control), GitHub +and BitBucket (for basic pull request based workflows), and Rietveld (for +CPython's optional pre-commit reviews). -In that role, I'll be focusing on effectively integrating the Developer -Bundle with tools and technologies used across Red Hat's project and product -portfolio. As Red Hat is an open source system integrator, that means -touching on a wide range of services and technologies, including GitHub, -GerritHub, standalone Gerrit, GitLab, Bugzilla, JIRA, Jenkins, Docker, -Kubernetes, OpenShift, OpenStack, oVirt, Ansible, Puppet, and more. - -However, as noted above in the section on sustaining engineering -considerations, I've also secured agreement to spend a portion of my work -time on similarly applying these cross platforms tools to improving the -developer experience for the maintenance of Python Software Foundation -infrastructure, starting with this proposal for a Kallithea-based -forge.python.org service. - -Between them, my day job and my personal open source engagement have given -me visibility into a lot of what the popular source code management -services do well and what they do poorly. While Kallithea certainly has -plenty of flaws of its own, it's the one I consider most *fixable* from a -personal perspective, as it allows me to get directly involved in tailoring -it to meet the needs of the CPython core development community in a way that -wouldn't be possible with a proprietary service like GitHub or BitBucket, or -practical with a PHP-based service like Phabricator or a Ruby-based service -like GitLab. +Kallithea is interesting as a base project to build, as it's currently a +combined repo hosting and code review management platform, but doesn't +directly integrate the two by offering online merges. This creates the +opportunity to blend the low barrier to entry benefits of the GitHub/BitBucket +pull request model with the mentoring and task hand-off benefits of Gerrit +in defining a online code merging model for Kallithea in collaboration with +the upstream Kallithea developers. Technical Concerns and Challenges @@ -418,6 +376,11 @@ Pilot Objectives and Timeline ============================= +[TODO: Update this section for Brett's revised timeline, which aims to have +a CPython demo repository online by October 31st, to get a better indication +of *future* capabilities once CPython itself migrates over to the new +system, rather than just the support repos] + This proposal is part of Brett Cannon's `current evaluation `__ of improvement proposals for various aspects of the CPython development -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 16:56:11 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 08 Aug 2015 14:56:11 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Cede_the_PEP_500_number_to_Al?= =?utf-8?q?exander_for_his_TZ_PEP?= Message-ID: <20150808145611.5511.55219@psf.io> https://hg.python.org/peps/rev/5d33702dc521 changeset: 5936:5d33702dc521 user: Nick Coghlan date: Sun Aug 09 00:55:03 2015 +1000 summary: Cede the PEP 500 number to Alexander for his TZ PEP files: pep-0501.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0500.txt b/pep-0501.txt rename from pep-0500.txt rename to pep-0501.txt --- a/pep-0500.txt +++ b/pep-0501.txt @@ -1,4 +1,4 @@ -PEP: 500 +PEP: 501 Title: Translation ready string interpolation Version: $Revision$ Last-Modified: $Date$ -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 16:56:11 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 08 Aug 2015 14:56:11 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_Fix_typo_reported_?= =?utf-8?q?by_Florian_Bruhin?= Message-ID: <20150808145611.111078.62170@psf.io> https://hg.python.org/peps/rev/7dc37e2dfb63 changeset: 5937:7dc37e2dfb63 user: Nick Coghlan date: Sun Aug 09 00:56:03 2015 +1000 summary: PEP 501: Fix typo reported by Florian Bruhin files: pep-0501.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -374,7 +374,7 @@ (https://www.python.org/dev/peps/pep-0215/) .. [#] PEP 292: Simpler String Substitutions - (https://www.python.org/dev/peps/pep-0215/) + (https://www.python.org/dev/peps/pep-0292/) .. [#] PEP 3101: Advanced String Formatting (https://www.python.org/dev/peps/pep-3101/) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 18:14:52 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 16:14:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NjM0?= =?utf-8?q?=3A_Importing_uuid_should_not_try_to_load_libc_on_Windows?= Message-ID: <20150808161420.29396.15582@psf.io> https://hg.python.org/cpython/rev/1df7a0821c73 changeset: 97330:1df7a0821c73 branch: 3.5 user: Steve Dower date: Tue Jul 14 13:25:03 2015 -0700 summary: Issue #24634: Importing uuid should not try to load libc on Windows files: Lib/uuid.py | 8 ++++++-- Misc/NEWS | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Lib/uuid.py b/Lib/uuid.py --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -459,10 +459,14 @@ _uuid_generate_random = _uuid_generate_time = _UuidCreate = None try: import ctypes, ctypes.util + import sys # The uuid_generate_* routines are provided by libuuid on at least # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: + _libnames = ['uuid'] + if not sys.platform.startswith('win'): + _libnames.append('c') + for libname in _libnames: try: lib = ctypes.CDLL(ctypes.util.find_library(libname)) except Exception: @@ -473,6 +477,7 @@ _uuid_generate_time = lib.uuid_generate_time if _uuid_generate_random is not None: break # found everything we were looking for + del _libnames # The uuid_generate_* functions are broken on MacOS X 10.5, as noted # in issue #8621 the function generates the same sequence of values @@ -481,7 +486,6 @@ # # Assume that the uuid_generate functions are broken from 10.5 onward, # the test can be adjusted when a later version is fixed. - import sys if sys.platform == 'darwin': import os if int(os.uname().release.split('.')[0]) >= 9: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,8 @@ Library ------- +- Issue #24634: Importing uuid should not try to load libc on Windows + - Issue #24798: _msvccompiler.py doesn't properly support manifests - Issue #4395: Better testing and documentation of binary operators. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 18:14:52 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 16:14:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Adds_documenta?= =?utf-8?q?tion_for_the_new_Windows_embedded_package=2E?= Message-ID: <20150808161420.29400.79411@psf.io> https://hg.python.org/cpython/rev/ab3087a2e813 changeset: 97329:ab3087a2e813 branch: 3.5 parent: 97327:d1ef54751412 user: Steve Dower date: Sat Aug 08 09:09:01 2015 -0700 summary: Adds documentation for the new Windows embedded package. files: Doc/using/windows.rst | 93 +++++++++++++++++++++++++++++- 1 files changed, 89 insertions(+), 4 deletions(-) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -42,9 +42,11 @@ If you select "Install Now": * You will *not* need to be an administrator (unless a system update for the - C Runtime Library is required) + C Runtime Library is required or you install the :ref:`launcher` for all + users) * Python will be installed into your user directory -* The :ref:`launcher` will *also* be installed into your user directory +* The :ref:`launcher` will be installed according to the option at the bottom + of the first pace * The standard library, test suite, launcher and pip will be installed * If selected, the install directory will be added to your :envvar:`PATH` * Shortcuts will only be visible for the current user @@ -60,7 +62,7 @@ * Python will be installed into the Program Files directory * The :ref:`launcher` will be installed into the Windows directory * Optional features may be selected during installation -* The standard library will be pre-compiled to bytecode +* The standard library can be pre-compiled to bytecode * If selected, the install directory will be added to the system :envvar:`PATH` * Shortcuts are available for all users @@ -649,6 +651,8 @@ +.. finding_modules: + Finding modules =============== @@ -718,6 +722,8 @@ * Include a ``pyvenv.cfg`` file alongside your executable containing ``applocal = true``. This will ensure that your own directory will be used to resolve paths even if you have included the standard library in a ZIP file. + It will also ignore user site-packages and other paths listed in the + registry. * If you are loading :file:`python3.dll` or :file:`python35.dll` in your own executable, explicitly call :c:func:`Py_SetPath` or (at least) @@ -733,7 +739,9 @@ These will ensure that the files in a system-wide installation will not take precedence over the copy of the standard library bundled with your application. -Otherwise, your users may experience problems using your application. +Otherwise, your users may experience problems using your application. Note that +the first suggestion is the best, as the other may still be susceptible to +non-standard paths in the registry and user site-packages. Additional modules ================== @@ -822,6 +830,83 @@ by Trent Apted et al, 2007 +Embedded Distribution +===================== + +.. versionadded:: 3.5 + +The embedded distribution is a ZIP file containing a minimal Python environment. +It is intended for acting as part of another application, rather than being +directly accessed by end-users. + +When extracted, the embedded distribution is (almost) fully isolated from the +user's system, including environment variables, system registry settings, and +installed packages. The standard library is included as pre-compiled and +optimized ``.pyc`` files in a ZIP, and ``python3.dll``, ``python35.dll``, +``python.exe`` and ``pythonw.exe`` are all provided. Tcl/tk (including all +dependants, such as Idle), pip and the Python documentation are not included. + +.. note:: + + The embedded distribution does not include the `Microsoft C Runtime + `_ and it is + the responsibility of the application installer to provide this. The + runtime may have already been installed on a user's system previously or + automatically via Windows Update, and can be detected by finding + ``ucrtbase.dll`` in the system directory. + +Third-party packages should be installed by the application installer alongside +the embedded distribution. Using pip to manage dependencies as for a regular +Python installation is not supported with this distribution, though with some +care it may be possible to include and use pip for automatic updates. In +general, third-party packages should be treated as part of the application +("vendoring") so that the developer can ensure compatibility with newer +versions before providing updates to users. + +The two recommended use cases for this distribution are described below. + +Python Application +------------------ + +An application written in Python does not necessarily require users to be aware +of that fact. The embedded distribution may be used in this case to include a +private version of Python in an install package. Depending on how transparent it +should be (or conversely, how professional it should appear), there are two +options. + +Using a specialized executable as a launcher requires some coding, but provides +the most transparent experience for users. With a customized launcher, there are +no obvious indications that the program is running on Python: icons can be +customized, company and version information can be specified, and file +associations behave properly. In most cases, a custom launcher should simply be +able to call ``Py_Main`` with a hard-coded command line. + +The simpler approach is to provide a batch file or generated shortcut that +directly calls the ``python.exe`` or ``pythonw.exe`` with the required +command-line arguments. In this case, the application will appear to be Python +and not its actual name, and users may have trouble distinguishing it from other +running Python processes or file associations. + +With the latter approach, packages should be installed as directories alongside +the Python executable to ensure they are available on the path. With the +specialized launcher, packages can be located in other locations as there is an +opportunity to specify the search path before launching the application. + +Embedding Python +---------------- + +Applications written in native code often require some form of scripting +language, and the embedded Python distribution can be used for this purpose. In +general, the majority of the application is in native code, and some part will +either invoke ``python.exe`` or directly use ``python3.dll``. For either case, +extracting the embedded distribution to a subdirectory of the application +installation is sufficient to provide a loadable Python interpreter. + +As with the application use, packages can be installed to any location as there +is an opportunity to specify search paths before initializing the interpreter. +Otherwise, there is no fundamental differences between using the embedded +distribution and a regular installation. + Other resources =============== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 18:24:59 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 16:24:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150808161420.5521.92506@psf.io> https://hg.python.org/cpython/rev/3eb4f96a3b30 changeset: 97331:3eb4f96a3b30 parent: 97328:c59b2c4f4cac parent: 97330:1df7a0821c73 user: Steve Dower date: Sat Aug 08 09:13:26 2015 -0700 summary: Merge with 3.5 files: Doc/using/windows.rst | 93 +++++++++++++++++++++++++++++- Lib/uuid.py | 8 ++- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -42,9 +42,11 @@ If you select "Install Now": * You will *not* need to be an administrator (unless a system update for the - C Runtime Library is required) + C Runtime Library is required or you install the :ref:`launcher` for all + users) * Python will be installed into your user directory -* The :ref:`launcher` will *also* be installed into your user directory +* The :ref:`launcher` will be installed according to the option at the bottom + of the first pace * The standard library, test suite, launcher and pip will be installed * If selected, the install directory will be added to your :envvar:`PATH` * Shortcuts will only be visible for the current user @@ -60,7 +62,7 @@ * Python will be installed into the Program Files directory * The :ref:`launcher` will be installed into the Windows directory * Optional features may be selected during installation -* The standard library will be pre-compiled to bytecode +* The standard library can be pre-compiled to bytecode * If selected, the install directory will be added to the system :envvar:`PATH` * Shortcuts are available for all users @@ -649,6 +651,8 @@ +.. finding_modules: + Finding modules =============== @@ -718,6 +722,8 @@ * Include a ``pyvenv.cfg`` file alongside your executable containing ``applocal = true``. This will ensure that your own directory will be used to resolve paths even if you have included the standard library in a ZIP file. + It will also ignore user site-packages and other paths listed in the + registry. * If you are loading :file:`python3.dll` or :file:`python35.dll` in your own executable, explicitly call :c:func:`Py_SetPath` or (at least) @@ -733,7 +739,9 @@ These will ensure that the files in a system-wide installation will not take precedence over the copy of the standard library bundled with your application. -Otherwise, your users may experience problems using your application. +Otherwise, your users may experience problems using your application. Note that +the first suggestion is the best, as the other may still be susceptible to +non-standard paths in the registry and user site-packages. Additional modules ================== @@ -822,6 +830,83 @@ by Trent Apted et al, 2007 +Embedded Distribution +===================== + +.. versionadded:: 3.5 + +The embedded distribution is a ZIP file containing a minimal Python environment. +It is intended for acting as part of another application, rather than being +directly accessed by end-users. + +When extracted, the embedded distribution is (almost) fully isolated from the +user's system, including environment variables, system registry settings, and +installed packages. The standard library is included as pre-compiled and +optimized ``.pyc`` files in a ZIP, and ``python3.dll``, ``python35.dll``, +``python.exe`` and ``pythonw.exe`` are all provided. Tcl/tk (including all +dependants, such as Idle), pip and the Python documentation are not included. + +.. note:: + + The embedded distribution does not include the `Microsoft C Runtime + `_ and it is + the responsibility of the application installer to provide this. The + runtime may have already been installed on a user's system previously or + automatically via Windows Update, and can be detected by finding + ``ucrtbase.dll`` in the system directory. + +Third-party packages should be installed by the application installer alongside +the embedded distribution. Using pip to manage dependencies as for a regular +Python installation is not supported with this distribution, though with some +care it may be possible to include and use pip for automatic updates. In +general, third-party packages should be treated as part of the application +("vendoring") so that the developer can ensure compatibility with newer +versions before providing updates to users. + +The two recommended use cases for this distribution are described below. + +Python Application +------------------ + +An application written in Python does not necessarily require users to be aware +of that fact. The embedded distribution may be used in this case to include a +private version of Python in an install package. Depending on how transparent it +should be (or conversely, how professional it should appear), there are two +options. + +Using a specialized executable as a launcher requires some coding, but provides +the most transparent experience for users. With a customized launcher, there are +no obvious indications that the program is running on Python: icons can be +customized, company and version information can be specified, and file +associations behave properly. In most cases, a custom launcher should simply be +able to call ``Py_Main`` with a hard-coded command line. + +The simpler approach is to provide a batch file or generated shortcut that +directly calls the ``python.exe`` or ``pythonw.exe`` with the required +command-line arguments. In this case, the application will appear to be Python +and not its actual name, and users may have trouble distinguishing it from other +running Python processes or file associations. + +With the latter approach, packages should be installed as directories alongside +the Python executable to ensure they are available on the path. With the +specialized launcher, packages can be located in other locations as there is an +opportunity to specify the search path before launching the application. + +Embedding Python +---------------- + +Applications written in native code often require some form of scripting +language, and the embedded Python distribution can be used for this purpose. In +general, the majority of the application is in native code, and some part will +either invoke ``python.exe`` or directly use ``python3.dll``. For either case, +extracting the embedded distribution to a subdirectory of the application +installation is sufficient to provide a loadable Python interpreter. + +As with the application use, packages can be installed to any location as there +is an opportunity to specify search paths before initializing the interpreter. +Otherwise, there is no fundamental differences between using the embedded +distribution and a regular installation. + Other resources =============== diff --git a/Lib/uuid.py b/Lib/uuid.py --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -459,10 +459,14 @@ _uuid_generate_random = _uuid_generate_time = _UuidCreate = None try: import ctypes, ctypes.util + import sys # The uuid_generate_* routines are provided by libuuid on at least # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: + _libnames = ['uuid'] + if not sys.platform.startswith('win'): + _libnames.append('c') + for libname in _libnames: try: lib = ctypes.CDLL(ctypes.util.find_library(libname)) except Exception: @@ -473,6 +477,7 @@ _uuid_generate_time = lib.uuid_generate_time if _uuid_generate_random is not None: break # found everything we were looking for + del _libnames # The uuid_generate_* functions are broken on MacOS X 10.5, as noted # in issue #8621 the function generates the same sequence of values @@ -481,7 +486,6 @@ # # Assume that the uuid_generate functions are broken from 10.5 onward, # the test can be adjusted when a later version is fixed. - import sys if sys.platform == 'darwin': import os if int(os.uname().release.split('.')[0]) >= 9: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 18:29:43 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 08 Aug 2015 16:29:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NjM0?= =?utf-8?q?=3A_Importing_uuid_should_not_try_to_load_libc_on_Windows?= Message-ID: <20150808161634.5529.2035@psf.io> https://hg.python.org/cpython/rev/90e2747425ad changeset: 97332:90e2747425ad branch: 2.7 parent: 97321:418095f0d711 user: Steve Dower date: Tue Jul 14 13:25:03 2015 -0700 summary: Issue #24634: Importing uuid should not try to load libc on Windows files: Lib/uuid.py | 8 ++++++-- Misc/NEWS | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Lib/uuid.py b/Lib/uuid.py --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -441,10 +441,14 @@ _uuid_generate_random = _uuid_generate_time = _UuidCreate = None try: import ctypes, ctypes.util + import sys # The uuid_generate_* routines are provided by libuuid on at least # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: + _libnames = ['uuid'] + if not sys.platform.startswith('win'): + _libnames.append('c') + for libname in _libnames: try: lib = ctypes.CDLL(ctypes.util.find_library(libname)) except: @@ -455,6 +459,7 @@ _uuid_generate_time = lib.uuid_generate_time if _uuid_generate_random is not None: break # found everything we were looking for + del _libnames # The uuid_generate_* functions are broken on MacOS X 10.5, as noted # in issue #8621 the function generates the same sequence of values @@ -463,7 +468,6 @@ # # Assume that the uuid_generate functions are broken from 10.5 onward, # the test can be adjusted when a later version is fixed. - import sys if sys.platform == 'darwin': import os if int(os.uname()[2].split('.')[0]) >= 9: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Library ------- +- Issue #24634: Importing uuid should not try to load libc on Windows + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Initial patch by Matt Frank. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 8 21:54:41 2015 From: python-checkins at python.org (brett.cannon) Date: Sat, 08 Aug 2015 19:54:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_a_Makefile_command_to_cre?= =?utf-8?q?ate_a_virtualenv_with_the_necessary_projects?= Message-ID: <20150808195441.110796.60586@psf.io> https://hg.python.org/peps/rev/508bd6101782 changeset: 5938:508bd6101782 user: Brett Cannon date: Sat Aug 08 12:54:36 2015 -0700 summary: Add a Makefile command to create a virtualenv with the necessary projects installed. files: .hgignore | 1 + Makefile | 4 ++++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -4,3 +4,4 @@ *.pyc *.pyo *~ +venv diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -33,3 +33,7 @@ update: hg pull -u https://hg.python.org/peps + +venv: + $(PYTHON) -m venv venv + ./venv/bin/python -m pip install -U docutils -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 23:04:06 2015 From: python-checkins at python.org (brett.cannon) Date: Sat, 08 Aug 2015 21:04:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_a_little_grammar=2E?= Message-ID: <20150808210406.29410.65138@psf.io> https://hg.python.org/peps/rev/92995b94611d changeset: 5939:92995b94611d user: Brett Cannon date: Sat Aug 08 14:03:59 2015 -0700 summary: Fix a little grammar. files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -160,7 +160,7 @@ corresponding single brace. Doubled opening braces do not signify the start of an expression. -Following the expression, an optionally the type conversion may be +Following the expression, an optional type conversion may be specified. The allowed conversions are '!s' or '!r'. These are treated the same as in str.format: '!s' calls str() on the expression, and '!r' calls repr() on the expression. These conversions are applied -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 8 23:04:33 2015 From: python-checkins at python.org (brett.cannon) Date: Sat, 08 Aug 2015 21:04:33 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Convert_all_PEP-related_code_?= =?utf-8?q?to_be_Python_2/3_compatible=2E?= Message-ID: <20150808210433.5515.51218@psf.io> https://hg.python.org/peps/rev/ed7ae7ebfc31 changeset: 5940:ed7ae7ebfc31 user: Brett Cannon date: Sat Aug 08 14:04:29 2015 -0700 summary: Convert all PEP-related code to be Python 2/3 compatible. files: genpepindex.py | 5 +- pep0/constants.py | 9 +- pep0/output.py | 156 +++++++++++++++++---------------- pep0/pep.py | 13 +- 4 files changed, 97 insertions(+), 86 deletions(-) diff --git a/genpepindex.py b/genpepindex.py --- a/genpepindex.py +++ b/genpepindex.py @@ -15,6 +15,7 @@ """ from __future__ import absolute_import, with_statement +from __future__ import print_function import sys import os @@ -48,10 +49,10 @@ raise PEPError('PEP number does not match file name', file_path, pep.number) peps.append(pep) - except PEPError, e: + except PEPError as e: errmsg = "Error processing PEP %s (%s), excluding:" % \ (e.number, e.filename) - print >>sys.stderr, errmsg, e + print(errmsg, e, file=sys.stderr) sys.exit(1) peps.sort(key=attrgetter('number')) elif os.path.isfile(path): diff --git a/pep0/constants.py b/pep0/constants.py --- a/pep0/constants.py +++ b/pep0/constants.py @@ -1,7 +1,14 @@ # -*- coding: utf-8 -*- +import sys + +if sys.version_info[0] > 2: + text_type = str +else: + text_type = unicode + title_length = 55 column_format = (u' %(type)1s%(status)1s %(number)4s %(title)-' + - unicode(title_length) + u's %(authors)-s') + text_type(title_length) + u's %(authors)-s') header = u"""PEP: 0 Title: Index of Python Enhancement Proposals (PEPs) diff --git a/pep0/output.py b/pep0/output.py --- a/pep0/output.py +++ b/pep0/output.py @@ -1,4 +1,6 @@ """Code to handle the output of PEP 0.""" +from __future__ import absolute_import +from __future__ import print_function import datetime import sys import unicodedata @@ -28,11 +30,11 @@ """Output the column headers for the PEP indices.""" column_headers = {'status': u'', 'type': u'', 'number': u'num', 'title': u'title', 'authors': u'owner'} - print>>output, constants.column_format % column_headers + print(constants.column_format % column_headers, file=output) underline_headers = {} for key, value in column_headers.items(): - underline_headers[key] = unicode(len(value) * '-') - print>>output, constants.column_format % underline_headers + underline_headers[key] = constants.text_type(len(value) * '-') + print(constants.column_format % underline_headers, file=output) def sort_peps(peps): @@ -120,7 +122,7 @@ def sort_authors(authors_dict): - authors_list = authors_dict.keys() + authors_list = list(authors_dict.keys()) authors_list.sort(key=attrgetter('sort_by')) return authors_list @@ -130,109 +132,109 @@ def write_pep0(peps, output=sys.stdout): today = datetime.date.today().strftime("%Y-%m-%d") - print>>output, constants.header % today - print>>output - print>>output, u"Introduction" - print>>output, constants.intro - print>>output - print>>output, u"Index by Category" - print>>output + print(constants.header % today, file=output) + print(file=output) + print(u"Introduction", file=output) + print(constants.intro, file=output) + print(file=output) + print(u"Index by Category", file=output) + print(file=output) write_column_headers(output) (meta, info, accepted, open_, finished, historical, deferred, dead) = sort_peps(peps) - print>>output - print>>output, u" Meta-PEPs (PEPs about PEPs or Processes)" - print>>output + print(file=output) + print(u" Meta-PEPs (PEPs about PEPs or Processes)", file=output) + print(file=output) for pep in meta: - print>>output, unicode(pep) - print>>output - print>>output, u" Other Informational PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Other Informational PEPs", file=output) + print(file=output) for pep in info: - print>>output, unicode(pep) - print>>output - print>>output, u" Accepted PEPs (accepted; may not be implemented yet)" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Accepted PEPs (accepted; may not be implemented yet)", file=output) + print(file=output) for pep in accepted: - print>>output, unicode(pep) - print>>output - print>>output, u" Open PEPs (under consideration)" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Open PEPs (under consideration)", file=output) + print(file=output) for pep in open_: - print>>output, unicode(pep) - print>>output - print>>output, u" Finished PEPs (done, implemented in code repository)" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Finished PEPs (done, implemented in code repository)", file=output) + print(file=output) for pep in finished: - print>>output, unicode(pep) - print>>output - print>>output, u" Historical Meta-PEPs and Informational PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Historical Meta-PEPs and Informational PEPs", file=output) + print(file=output) for pep in historical: - print>>output, unicode(pep) - print>>output - print>>output, u" Deferred PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Deferred PEPs", file=output) + print(file=output) for pep in deferred: - print>>output, unicode(pep) - print>>output - print>>output, u" Abandoned, Withdrawn, and Rejected PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Abandoned, Withdrawn, and Rejected PEPs", file=output) + print(file=output) for pep in dead: - print>>output, unicode(pep) - print>>output - print>>output - print>>output, u"Numerical Index" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(file=output) + print(u"Numerical Index", file=output) + print(file=output) write_column_headers(output) prev_pep = 0 for pep in peps: if pep.number - prev_pep > 1: - print>>output - print>>output, unicode(pep) + print(file=output) + print(constants.text_type(pep), file=output) prev_pep = pep.number - print>>output - print>>output - print>>output, u'Reserved PEP Numbers' - print>>output + print(file=output) + print(file=output) + print(u'Reserved PEP Numbers', file=output) + print(file=output) write_column_headers(output) for number, claimants in sorted(RESERVED): - print>>output, constants.column_format % { + print(constants.column_format % { 'type': '', 'status': '', 'number': number, 'title': 'RESERVED', 'authors': claimants, - } - print>>output - print>>output - print>>output, u"Key" - print>>output + }, file=output) + print(file=output) + print(file=output) + print(u"Key", file=output) + print(file=output) for type_ in PEP.type_values: - print>>output, u" %s - %s PEP" % (type_[0], type_) - print>>output + print(u" %s - %s PEP" % (type_[0], type_), file=output) + print(file=output) for status in PEP.status_values: - print>>output, u" %s - %s proposal" % (status[0], status) + print(u" %s - %s proposal" % (status[0], status), file=output) - print>>output - print>>output - print>>output, u"Owners" - print>>output + print(file=output) + print(file=output) + print(u"Owners", file=output) + print(file=output) authors_dict = verify_email_addresses(peps) max_name = max(authors_dict.keys(), key=normalized_last_first) max_name_len = len(max_name.last_first) - print>>output, u" %s %s" % ('name'.ljust(max_name_len), 'email address') - print>>output, u" %s %s" % ((len('name')*'-').ljust(max_name_len), - len('email address')*'-') + print(u" %s %s" % ('name'.ljust(max_name_len), 'email address'), file=output) + print(u" %s %s" % ((len('name')*'-').ljust(max_name_len), + len('email address')*'-'), file=output) sorted_authors = sort_authors(authors_dict) for author in sorted_authors: # Use the email from authors_dict instead of the one from 'author' as # the author instance may have an empty email. - print>>output, (u" %s %s" % - (author.last_first.ljust(max_name_len), authors_dict[author])) - print>>output - print>>output - print>>output, u"References" - print>>output - print>>output, constants.references - print>>output, constants.footer + print((u" %s %s" % + (author.last_first.ljust(max_name_len), authors_dict[author])), file=output) + print(file=output) + print(file=output) + print(u"References", file=output) + print(file=output) + print(constants.references, file=output) + print(constants.footer, file=output) diff --git a/pep0/pep.py b/pep0/pep.py --- a/pep0/pep.py +++ b/pep0/pep.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Code for handling object representation of a PEP.""" +from __future__ import absolute_import import re import textwrap import unicodedata @@ -179,9 +180,9 @@ header_order = iter(self.headers) try: for header_name in metadata.keys(): - current_header, required = header_order.next() + current_header, required = next(header_order) while header_name != current_header and not required: - current_header, required = header_order.next() + current_header, required = next(header_order) if header_name != current_header: raise PEPError("did not deal with " "%r before having to handle %r" % @@ -193,7 +194,7 @@ required = False try: while not required: - current_header, required = header_order.next() + current_header, required = next(header_order) else: raise PEPError("PEP is missing its %r" % (current_header,), pep_file.name) @@ -239,9 +240,9 @@ """Return a list of author names and emails.""" # XXX Consider using email.utils.parseaddr (doesn't work with names # lacking an email address. - angled = ur'(?P.+?) <(?P.+?)>' - paren = ur'(?P.+?) \((?P.+?)\)' - simple = ur'(?P[^,]+)' + angled = constants.text_type(r'(?P.+?) <(?P.+?)>') + paren = constants.text_type(r'(?P.+?) \((?P.+?)\)') + simple = constants.text_type(r'(?P[^,]+)') author_list = [] for regex in (angled, paren, simple): # Watch out for commas separating multiple names. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 9 00:08:13 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 08 Aug 2015 22:08:13 +0000 Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_merge?= Message-ID: <20150808220812.23398.31931@psf.io> https://hg.python.org/peps/rev/c76c2a9a012b changeset: 5942:c76c2a9a012b parent: 5941:3ebed99e530f parent: 5940:ed7ae7ebfc31 user: Alexander Belopolsky date: Sat Aug 08 18:08:06 2015 -0400 summary: merge files: .hgignore | 1 + Makefile | 4 + genpepindex.py | 5 +- pep-0498.txt | 2 +- pep0/constants.py | 9 +- pep0/output.py | 156 +++++++++++++++++---------------- pep0/pep.py | 13 +- 7 files changed, 103 insertions(+), 87 deletions(-) diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -4,3 +4,4 @@ *.pyc *.pyo *~ +venv diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -33,3 +33,7 @@ update: hg pull -u https://hg.python.org/peps + +venv: + $(PYTHON) -m venv venv + ./venv/bin/python -m pip install -U docutils diff --git a/genpepindex.py b/genpepindex.py --- a/genpepindex.py +++ b/genpepindex.py @@ -15,6 +15,7 @@ """ from __future__ import absolute_import, with_statement +from __future__ import print_function import sys import os @@ -48,10 +49,10 @@ raise PEPError('PEP number does not match file name', file_path, pep.number) peps.append(pep) - except PEPError, e: + except PEPError as e: errmsg = "Error processing PEP %s (%s), excluding:" % \ (e.number, e.filename) - print >>sys.stderr, errmsg, e + print(errmsg, e, file=sys.stderr) sys.exit(1) peps.sort(key=attrgetter('number')) elif os.path.isfile(path): diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -160,7 +160,7 @@ corresponding single brace. Doubled opening braces do not signify the start of an expression. -Following the expression, an optionally the type conversion may be +Following the expression, an optional type conversion may be specified. The allowed conversions are '!s' or '!r'. These are treated the same as in str.format: '!s' calls str() on the expression, and '!r' calls repr() on the expression. These conversions are applied diff --git a/pep0/constants.py b/pep0/constants.py --- a/pep0/constants.py +++ b/pep0/constants.py @@ -1,7 +1,14 @@ # -*- coding: utf-8 -*- +import sys + +if sys.version_info[0] > 2: + text_type = str +else: + text_type = unicode + title_length = 55 column_format = (u' %(type)1s%(status)1s %(number)4s %(title)-' + - unicode(title_length) + u's %(authors)-s') + text_type(title_length) + u's %(authors)-s') header = u"""PEP: 0 Title: Index of Python Enhancement Proposals (PEPs) diff --git a/pep0/output.py b/pep0/output.py --- a/pep0/output.py +++ b/pep0/output.py @@ -1,4 +1,6 @@ """Code to handle the output of PEP 0.""" +from __future__ import absolute_import +from __future__ import print_function import datetime import sys import unicodedata @@ -28,11 +30,11 @@ """Output the column headers for the PEP indices.""" column_headers = {'status': u'', 'type': u'', 'number': u'num', 'title': u'title', 'authors': u'owner'} - print>>output, constants.column_format % column_headers + print(constants.column_format % column_headers, file=output) underline_headers = {} for key, value in column_headers.items(): - underline_headers[key] = unicode(len(value) * '-') - print>>output, constants.column_format % underline_headers + underline_headers[key] = constants.text_type(len(value) * '-') + print(constants.column_format % underline_headers, file=output) def sort_peps(peps): @@ -120,7 +122,7 @@ def sort_authors(authors_dict): - authors_list = authors_dict.keys() + authors_list = list(authors_dict.keys()) authors_list.sort(key=attrgetter('sort_by')) return authors_list @@ -130,109 +132,109 @@ def write_pep0(peps, output=sys.stdout): today = datetime.date.today().strftime("%Y-%m-%d") - print>>output, constants.header % today - print>>output - print>>output, u"Introduction" - print>>output, constants.intro - print>>output - print>>output, u"Index by Category" - print>>output + print(constants.header % today, file=output) + print(file=output) + print(u"Introduction", file=output) + print(constants.intro, file=output) + print(file=output) + print(u"Index by Category", file=output) + print(file=output) write_column_headers(output) (meta, info, accepted, open_, finished, historical, deferred, dead) = sort_peps(peps) - print>>output - print>>output, u" Meta-PEPs (PEPs about PEPs or Processes)" - print>>output + print(file=output) + print(u" Meta-PEPs (PEPs about PEPs or Processes)", file=output) + print(file=output) for pep in meta: - print>>output, unicode(pep) - print>>output - print>>output, u" Other Informational PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Other Informational PEPs", file=output) + print(file=output) for pep in info: - print>>output, unicode(pep) - print>>output - print>>output, u" Accepted PEPs (accepted; may not be implemented yet)" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Accepted PEPs (accepted; may not be implemented yet)", file=output) + print(file=output) for pep in accepted: - print>>output, unicode(pep) - print>>output - print>>output, u" Open PEPs (under consideration)" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Open PEPs (under consideration)", file=output) + print(file=output) for pep in open_: - print>>output, unicode(pep) - print>>output - print>>output, u" Finished PEPs (done, implemented in code repository)" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Finished PEPs (done, implemented in code repository)", file=output) + print(file=output) for pep in finished: - print>>output, unicode(pep) - print>>output - print>>output, u" Historical Meta-PEPs and Informational PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Historical Meta-PEPs and Informational PEPs", file=output) + print(file=output) for pep in historical: - print>>output, unicode(pep) - print>>output - print>>output, u" Deferred PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Deferred PEPs", file=output) + print(file=output) for pep in deferred: - print>>output, unicode(pep) - print>>output - print>>output, u" Abandoned, Withdrawn, and Rejected PEPs" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(u" Abandoned, Withdrawn, and Rejected PEPs", file=output) + print(file=output) for pep in dead: - print>>output, unicode(pep) - print>>output - print>>output - print>>output, u"Numerical Index" - print>>output + print(constants.text_type(pep), file=output) + print(file=output) + print(file=output) + print(u"Numerical Index", file=output) + print(file=output) write_column_headers(output) prev_pep = 0 for pep in peps: if pep.number - prev_pep > 1: - print>>output - print>>output, unicode(pep) + print(file=output) + print(constants.text_type(pep), file=output) prev_pep = pep.number - print>>output - print>>output - print>>output, u'Reserved PEP Numbers' - print>>output + print(file=output) + print(file=output) + print(u'Reserved PEP Numbers', file=output) + print(file=output) write_column_headers(output) for number, claimants in sorted(RESERVED): - print>>output, constants.column_format % { + print(constants.column_format % { 'type': '', 'status': '', 'number': number, 'title': 'RESERVED', 'authors': claimants, - } - print>>output - print>>output - print>>output, u"Key" - print>>output + }, file=output) + print(file=output) + print(file=output) + print(u"Key", file=output) + print(file=output) for type_ in PEP.type_values: - print>>output, u" %s - %s PEP" % (type_[0], type_) - print>>output + print(u" %s - %s PEP" % (type_[0], type_), file=output) + print(file=output) for status in PEP.status_values: - print>>output, u" %s - %s proposal" % (status[0], status) + print(u" %s - %s proposal" % (status[0], status), file=output) - print>>output - print>>output - print>>output, u"Owners" - print>>output + print(file=output) + print(file=output) + print(u"Owners", file=output) + print(file=output) authors_dict = verify_email_addresses(peps) max_name = max(authors_dict.keys(), key=normalized_last_first) max_name_len = len(max_name.last_first) - print>>output, u" %s %s" % ('name'.ljust(max_name_len), 'email address') - print>>output, u" %s %s" % ((len('name')*'-').ljust(max_name_len), - len('email address')*'-') + print(u" %s %s" % ('name'.ljust(max_name_len), 'email address'), file=output) + print(u" %s %s" % ((len('name')*'-').ljust(max_name_len), + len('email address')*'-'), file=output) sorted_authors = sort_authors(authors_dict) for author in sorted_authors: # Use the email from authors_dict instead of the one from 'author' as # the author instance may have an empty email. - print>>output, (u" %s %s" % - (author.last_first.ljust(max_name_len), authors_dict[author])) - print>>output - print>>output - print>>output, u"References" - print>>output - print>>output, constants.references - print>>output, constants.footer + print((u" %s %s" % + (author.last_first.ljust(max_name_len), authors_dict[author])), file=output) + print(file=output) + print(file=output) + print(u"References", file=output) + print(file=output) + print(constants.references, file=output) + print(constants.footer, file=output) diff --git a/pep0/pep.py b/pep0/pep.py --- a/pep0/pep.py +++ b/pep0/pep.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Code for handling object representation of a PEP.""" +from __future__ import absolute_import import re import textwrap import unicodedata @@ -179,9 +180,9 @@ header_order = iter(self.headers) try: for header_name in metadata.keys(): - current_header, required = header_order.next() + current_header, required = next(header_order) while header_name != current_header and not required: - current_header, required = header_order.next() + current_header, required = next(header_order) if header_name != current_header: raise PEPError("did not deal with " "%r before having to handle %r" % @@ -193,7 +194,7 @@ required = False try: while not required: - current_header, required = header_order.next() + current_header, required = next(header_order) else: raise PEPError("PEP is missing its %r" % (current_header,), pep_file.name) @@ -239,9 +240,9 @@ """Return a list of author names and emails.""" # XXX Consider using email.utils.parseaddr (doesn't work with names # lacking an email address. - angled = ur'(?P.+?) <(?P.+?)>' - paren = ur'(?P.+?) \((?P.+?)\)' - simple = ur'(?P[^,]+)' + angled = constants.text_type(r'(?P.+?) <(?P.+?)>') + paren = constants.text_type(r'(?P.+?) \((?P.+?)\)') + simple = constants.text_type(r'(?P[^,]+)') author_list = [] for regex in (angled, paren, simple): # Watch out for commas separating multiple names. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 9 00:08:12 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 08 Aug 2015 22:08:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP-0500=3A_A_protocol_for_de?= =?utf-8?q?legating_datetime_methods?= Message-ID: <20150808220812.17731.61730@psf.io> https://hg.python.org/peps/rev/3ebed99e530f changeset: 5941:3ebed99e530f parent: 5937:7dc37e2dfb63 user: Alexander Belopolsky date: Sat Aug 08 18:07:27 2015 -0400 summary: PEP-0500: A protocol for delegating datetime methods files: pep-0500.txt | 204 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 204 insertions(+), 0 deletions(-) diff --git a/pep-0500.txt b/pep-0500.txt new file mode 100644 --- /dev/null +++ b/pep-0500.txt @@ -0,0 +1,204 @@ +PEP: 500 +Title: A protocol for delegating datetime methods to their + tzinfo implementations +Version: $Revision$ +Last-Modified: $Date$ +Author: Alexander Belopolsky +Discussions-To: Datetime-SIG +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Requires: 495 +Created: 08-Aug-2015 + + +Abstract +======== + +This PEP specifies a new protocol (PDDM - "A Protocol for Delegating +Datetime Methods") that can be used by concrete implementations of the +``datetime.tzinfo`` interface to override aware datetime arithmetics, +formatting and parsing. We describe changes to the +``datetime.datetime`` class to support the new protocol and propose a +new abstract class ``datetime.tzstrict`` that implements parts of this +protocol necessary to make aware datetime instances to follow "strict" +arithmetic rules. + + +Rationale +========= + +As of Python 3.5, aware datetime instances that share a ``tzinfo`` +object follow the rules of arithmetics that are induced by a simple +bijection between (year, month, day, hour, minute, second, +microsecond) 7-tuples and large integers. In this arithmetics, the +difference between YEAR-11-02T12:00 and YEAR-11-01T12:00 is always 24 +hours, even though in the US/Eastern timezone, for example, there are +25 hours between 2014-11-01T12:00 and 2014-11-02T12:00 because the +local clocks were rolled back one hour at 2014-11-02T02:00, +introducing an extra hour in the night between 2014-11-01 and +2014-11-02. + +Many business applications requre the use of Python's simplified view +of local dates. No self-respecting car rental company will charge its +customers more for a week that straddles the end of DST than for any +other week or require that they return the car an hour early. +Therefore, changing the current rules for aware datetime arithmentics +will not only create a backward compatibility nightmare, it will +eliminate support for legitimate and common use cases. + +Since it is impossible to choose universal rules for local time +arithmetics, we propose to delegate implementation of those rules to +the classes that implement ``datetime.tzinfo`` interface. With such +delegation in place, users will be able to choose between different +arithmetics by simply picking instances of different classes for the +value of ``tzinfo``. + + +Protocol +======== + +Subtraction of datetime +----------------------- + +A ``tzinfo`` subclass supporting the PDDM, may define a method called +``__datetime_diff__`` that should take two ``datetime.datetime`` +instances and return a ``datetime.timedelta`` instance representing +the time elapced from the time represented by the first datetime +instance to another. + + +Addition +-------- + +A ``tzinfo`` subclass supporting the PDDM, may define a method called +``__datetime_add__`` that should take two arguments--a datetime and a +timedelta instances--and return a datetime instance. + + +Subtraction of timedelta +------------------------ + +A ``tzinfo`` subclass supporting the PDDM, may define a method called +``__datetime_sub__`` that should take two arguments--a datetime and a +timedelta instances--and return a datetime instance. + + +Formatting +---------- + +A ``tzinfo`` subclass supporting the PDDM, may define methods called +``__datetime_isoformat__`` and ``__datetime_strftime__``. + +The ``__datetime_isoformat__`` method should take a datetime instance +and an optional separator and produce a string representation of the +given datetime instance. + +The ``__datetime_strftime__`` method should take a datetime instance +and a format string and produce a string representation of the given +datetime instance formatted according to the given format. + + +Parsing +------- + +A ``tzinfo`` subclass supporting the PDDM, may define a class method +called ``__datetime_strptime__`` and register the "canonical" names of +the timezones that it implements with a registry. **TODO** Describe a +registry. + + +Changes to datetime methods +=========================== + +Subtraction +----------- + +:: + + class datetime: + def __sub__(self, other): + if isinstance(other, datetime): + try: + self_diff = self.tzinfo.__datetime_diff__ + except AttributeError: + self_diff = None + try: + other_diff = self.tzinfo.__datetime_diff__ + except AttributeError: + other_diff = None + if self_diff is not None: + if self_diff is not other_diff and self_diff.__func__ is not other_diff.__func__: + raise ValueError("Cannot find difference of two datetimes with " + "different tzinfo.__datetime_diff__ implementations.") + return self_diff(self, other) + elif isinstance(other, timedelta): + try: + sub = self.tzinfo.__datetime_sub__ + except AttributeError: + pass + else: + return sub(self, other) + return self + -other + else: + return NotImplemented + # current implementation + + +Addition +-------- + +Addition of a timedelta to a datetime instance will be delegated to the +``self.tzinfo.__datetime_add__`` method whenever it is defined. + + +Strict arithmetics +================== + +A new abstract subclass of ``datetime.tzinfo`` class called ``datetime.tzstrict`` +will be added to the ``datetime`` module. This subclass will not implement the +``utcoffset()``, ``tzname()`` or ``dst()`` methods, but will implement some of the +methods of the PDDM. + +The PDDM methods implemented by ``tzstrict`` will be equivalent to the following:: + + class tzstrict(tzinfo): + def __datetime_diff__(self, dt1, dt2): + utc_dt1 = dt1.astimezone(timezone.utc) + utc_dt2 = dt2.astimezone(timezone.utc) + return utc_dt2 - utc_dt1 + + def __datetime_add__(self, dt, delta): + utc_dt = dt.astimezone(timezone.utc) + return (utc_dt + delta).astimezone(self) + + def __datetime_sub__(self, dt, delta): + utc_dt = dt.astimezone(timezone.utc) + return (utc_dt - delta).astimezone(self) + + +Parsing and formatting +---------------------- + +Datetime methods ``strftime`` and ``isoformat`` will delegate to the namesake +methods of their ``tzinfo`` members whenever those methods are defined. + +When the ``datetime.strptime`` method is given a format string that +contains a ``%Z`` instruction, it will lookup the ``tzinfo`` +implementation in the registry by the given timezone name and call its +``__datetime_strptime__`` method. + +Applications +============ + +This PEP will enable third party implementation of many different +timekeeping schemes including: + +* Julian / Microsoft Excel calendar. +* "Right" timezones with the leap second support. +* French revolutionary calendar (with a lot of work). + +Copyright +========= + +This document has been placed in the public domain. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 9 00:17:12 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 08 Aug 2015 22:17:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Corrected_a_typo_in_PEP-0500?= =?utf-8?q?=2E?= Message-ID: <20150808221712.1383.42370@psf.io> https://hg.python.org/peps/rev/578f401e66b4 changeset: 5943:578f401e66b4 user: Alexander Belopolsky date: Sat Aug 08 18:17:08 2015 -0400 summary: Corrected a typo in PEP-0500. files: pep-0500.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0500.txt b/pep-0500.txt --- a/pep-0500.txt +++ b/pep-0500.txt @@ -43,7 +43,7 @@ of local dates. No self-respecting car rental company will charge its customers more for a week that straddles the end of DST than for any other week or require that they return the car an hour early. -Therefore, changing the current rules for aware datetime arithmentics +Therefore, changing the current rules for aware datetime arithmetics will not only create a backward compatibility nightmare, it will eliminate support for legitimate and common use cases. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 9 05:05:45 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 09 Aug 2015 03:05:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4?= Message-ID: <20150809030545.17733.87425@psf.io> https://hg.python.org/cpython/rev/bd0e3409e207 changeset: 97335:bd0e3409e207 branch: 3.5 parent: 97330:1df7a0821c73 parent: 97334:56f4327d3c57 user: Zachary Ware date: Sat Aug 08 22:03:43 2015 -0500 summary: Merge 3.4 files: Lib/test/regrtest.py | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -796,10 +796,8 @@ for time, test in test_times[:10]: print("%s: %.1fs" % (test, time)) if bad: - bad = sorted(set(bad) - set(environment_changed)) - if bad: - print(count(len(bad), "test"), "failed:") - printlist(bad) + print(count(len(bad), "test"), "failed:") + printlist(bad) if environment_changed: print("{} altered the execution environment:".format( count(len(environment_changed), "test"))) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 05:05:45 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 09 Aug 2015 03:05:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150809030545.23398.60633@psf.io> https://hg.python.org/cpython/rev/57032f6ca3ce changeset: 97336:57032f6ca3ce parent: 97331:3eb4f96a3b30 parent: 97335:bd0e3409e207 user: Zachary Ware date: Sat Aug 08 22:05:05 2015 -0500 summary: Merge 3.5 files: Lib/test/regrtest.py | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -796,10 +796,8 @@ for time, test in test_times[:10]: print("%s: %.1fs" % (test, time)) if bad: - bad = sorted(set(bad) - set(environment_changed)) - if bad: - print(count(len(bad), "test"), "failed:") - printlist(bad) + print(count(len(bad), "test"), "failed:") + printlist(bad) if environment_changed: print("{} altered the execution environment:".format( count(len(environment_changed), "test"))) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 05:05:45 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 09 Aug 2015 03:05:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogcmVncnRlc3Q6IHRo?= =?utf-8?q?e_=27bad=27_and_=27environment=5Fchanged=27_sets_of_tests_don?= =?utf-8?q?=27t_intersect?= Message-ID: <20150809030545.29404.100@psf.io> https://hg.python.org/cpython/rev/56f4327d3c57 changeset: 97334:56f4327d3c57 branch: 3.4 parent: 97322:7c322c296a3b user: Zachary Ware date: Sat Aug 08 22:03:27 2015 -0500 summary: regrtest: the 'bad' and 'environment_changed' sets of tests don't intersect anymore files: Lib/test/regrtest.py | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -798,10 +798,8 @@ for time, test in test_times[:10]: print("%s: %.1fs" % (test, time)) if bad: - bad = sorted(set(bad) - set(environment_changed)) - if bad: - print(count(len(bad), "test"), "failed:") - printlist(bad) + print(count(len(bad), "test"), "failed:") + printlist(bad) if environment_changed: print("{} altered the execution environment:".format( count(len(environment_changed), "test"))) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 05:05:45 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 09 Aug 2015 03:05:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0NzUx?= =?utf-8?q?=3A_Fix_running_regrtest_with_=27-w=27_flag_in_case_of_test_fai?= =?utf-8?q?lures=2E?= Message-ID: <20150809030545.94774.49@psf.io> https://hg.python.org/cpython/rev/7d69b214e668 changeset: 97333:7d69b214e668 branch: 2.7 user: Zachary Ware date: Sat Aug 08 22:01:20 2015 -0500 summary: Issue #24751: Fix running regrtest with '-w' flag in case of test failures. Also fixes reporting of tests that change environment when there are no test failures. files: Lib/test/regrtest.py | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -624,14 +624,12 @@ for time, test in test_times[:10]: print "%s: %.1fs" % (test, time) if bad: - bad = set(bad) - set(environment_changed) - if bad: - print count(len(bad), "test"), "failed:" - printlist(bad) - if environment_changed: - print "{} altered the execution environment:".format( - count(len(environment_changed), "test")) - printlist(environment_changed) + print count(len(bad), "test"), "failed:" + printlist(bad) + if environment_changed: + print "{} altered the execution environment:".format( + count(len(environment_changed), "test")) + printlist(environment_changed) if skipped and not quiet: print count(len(skipped), "test"), "skipped:" printlist(skipped) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 09:35:14 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 09 Aug 2015 07:35:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_more_tests_of_hash_eff?= =?utf-8?q?ectiveness=2E?= Message-ID: <20150809073514.29402.32789@psf.io> https://hg.python.org/cpython/rev/1d0038dbd8f8 changeset: 97337:1d0038dbd8f8 user: Raymond Hettinger date: Sun Aug 09 00:35:00 2015 -0700 summary: Add more tests of hash effectiveness. files: Lib/test/test_set.py | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -10,6 +10,8 @@ import warnings import collections import collections.abc +import itertools +import string class PassThru(Exception): pass @@ -711,6 +713,28 @@ addhashvalue(hash(frozenset([e for e, m in elemmasks if m&i]))) self.assertEqual(len(hashvalues), 2**n) + def letter_range(n): + return string.ascii_letters[:n] + + def zf_range(n): + # https://en.wikipedia.org/wiki/Set-theoretic_definition_of_natural_numbers + nums = [frozenset()] + for i in range(n-1): + num = frozenset(nums) + nums.append(num) + return nums[:n] + + def powerset(s): + for i in range(len(s)+1): + yield from map(frozenset, itertools.combinations(s, i)) + + for n in range(18): + t = 2 ** n + mask = t - 1 + for nums in (range, letter_range, zf_range): + u = len({h & mask for h in map(hash, powerset(nums(n)))}) + self.assertGreater(4*u, t) + class FrozenSetSubclass(frozenset): pass -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 11:25:55 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 09:25:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODI0?= =?utf-8?q?=3A_Signatures_of_codecs=2Eencode=28=29_and_codecs=2Edecode=28?= =?utf-8?q?=29_now_are?= Message-ID: <20150809092554.29394.67989@psf.io> https://hg.python.org/cpython/rev/bdd1df816f84 changeset: 97338:bdd1df816f84 branch: 3.5 parent: 97335:bd0e3409e207 user: Serhiy Storchaka date: Sun Aug 09 12:23:08 2015 +0300 summary: Issue #24824: Signatures of codecs.encode() and codecs.decode() now are compatible with pydoc. files: Misc/NEWS | 3 +++ Modules/_codecsmodule.c | 12 ++++++------ Modules/clinic/_codecsmodule.c.h | 12 +++++------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #24824: Signatures of codecs.encode() and codecs.decode() now are + compatible with pydoc. + - Issue #24634: Importing uuid should not try to load libc on Windows - Issue #24798: _msvccompiler.py doesn't properly support manifests diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -91,12 +91,12 @@ /*[clinic input] _codecs.encode obj: object - encoding: str(c_default="NULL") = sys.getdefaultencoding() + encoding: str(c_default="NULL") = "utf-8" errors: str(c_default="NULL") = "strict" Encodes obj using the codec registered for encoding. -encoding defaults to the default encoding. errors may be given to set a +The default encoding is 'utf-8'. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a ValueError. Other possible values are 'ignore', 'replace' and 'backslashreplace' as well as any other name registered with @@ -106,7 +106,7 @@ static PyObject * _codecs_encode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, const char *errors) -/*[clinic end generated code: output=5c073f62249c8d7c input=2440d769df020a0e]*/ +/*[clinic end generated code: output=5c073f62249c8d7c input=cd5b685040ff61f0]*/ { if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); @@ -118,12 +118,12 @@ /*[clinic input] _codecs.decode obj: object - encoding: str(c_default="NULL") = sys.getdefaultencoding() + encoding: str(c_default="NULL") = "utf-8" errors: str(c_default="NULL") = "strict" Decodes obj using the codec registered for encoding. -encoding defaults to the default encoding. errors may be given to set a +Default encoding is 'utf-8'. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a ValueError. Other possible values are 'ignore', 'replace' and 'backslashreplace' as well as any other name registered with @@ -133,7 +133,7 @@ static PyObject * _codecs_decode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, const char *errors) -/*[clinic end generated code: output=c81cbf6189a7f878 input=a351e5f5baad1544]*/ +/*[clinic end generated code: output=c81cbf6189a7f878 input=7702c0cc2fa1add6]*/ { if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -42,13 +42,12 @@ } PyDoc_STRVAR(_codecs_encode__doc__, -"encode($module, /, obj, encoding=sys.getdefaultencoding(),\n" -" errors=\'strict\')\n" +"encode($module, /, obj, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" "\n" "Encodes obj using the codec registered for encoding.\n" "\n" -"encoding defaults to the default encoding. errors may be given to set a\n" +"The default encoding is \'utf-8\'. errors may be given to set a\n" "different error handling scheme. Default is \'strict\' meaning that encoding\n" "errors raise a ValueError. Other possible values are \'ignore\', \'replace\'\n" "and \'backslashreplace\' as well as any other name registered with\n" @@ -80,13 +79,12 @@ } PyDoc_STRVAR(_codecs_decode__doc__, -"decode($module, /, obj, encoding=sys.getdefaultencoding(),\n" -" errors=\'strict\')\n" +"decode($module, /, obj, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" "\n" "Decodes obj using the codec registered for encoding.\n" "\n" -"encoding defaults to the default encoding. errors may be given to set a\n" +"Default encoding is \'utf-8\'. errors may be given to set a\n" "different error handling scheme. Default is \'strict\' meaning that encoding\n" "errors raise a ValueError. Other possible values are \'ignore\', \'replace\'\n" "and \'backslashreplace\' as well as any other name registered with\n" @@ -1395,4 +1393,4 @@ #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=713a4081788da1bc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9c9967048027c1c7 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 11:25:55 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 09:25:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324824=3A_Signatures_of_codecs=2Eencode=28=29_an?= =?utf-8?q?d_codecs=2Edecode=28=29_now_are?= Message-ID: <20150809092555.111120.83241@psf.io> https://hg.python.org/cpython/rev/ad65cad76331 changeset: 97339:ad65cad76331 parent: 97337:1d0038dbd8f8 parent: 97338:bdd1df816f84 user: Serhiy Storchaka date: Sun Aug 09 12:25:07 2015 +0300 summary: Issue #24824: Signatures of codecs.encode() and codecs.decode() now are compatible with pydoc. files: Misc/NEWS | 3 +++ Modules/_codecsmodule.c | 12 ++++++------ Modules/clinic/_codecsmodule.c.h | 12 +++++------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #24824: Signatures of codecs.encode() and codecs.decode() now are + compatible with pydoc. + - Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -91,12 +91,12 @@ /*[clinic input] _codecs.encode obj: object - encoding: str(c_default="NULL") = sys.getdefaultencoding() + encoding: str(c_default="NULL") = "utf-8" errors: str(c_default="NULL") = "strict" Encodes obj using the codec registered for encoding. -encoding defaults to the default encoding. errors may be given to set a +The default encoding is 'utf-8'. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a ValueError. Other possible values are 'ignore', 'replace' and 'backslashreplace' as well as any other name registered with @@ -106,7 +106,7 @@ static PyObject * _codecs_encode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, const char *errors) -/*[clinic end generated code: output=5c073f62249c8d7c input=2440d769df020a0e]*/ +/*[clinic end generated code: output=5c073f62249c8d7c input=cd5b685040ff61f0]*/ { if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); @@ -118,12 +118,12 @@ /*[clinic input] _codecs.decode obj: object - encoding: str(c_default="NULL") = sys.getdefaultencoding() + encoding: str(c_default="NULL") = "utf-8" errors: str(c_default="NULL") = "strict" Decodes obj using the codec registered for encoding. -encoding defaults to the default encoding. errors may be given to set a +Default encoding is 'utf-8'. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a ValueError. Other possible values are 'ignore', 'replace' and 'backslashreplace' as well as any other name registered with @@ -133,7 +133,7 @@ static PyObject * _codecs_decode_impl(PyModuleDef *module, PyObject *obj, const char *encoding, const char *errors) -/*[clinic end generated code: output=c81cbf6189a7f878 input=a351e5f5baad1544]*/ +/*[clinic end generated code: output=c81cbf6189a7f878 input=7702c0cc2fa1add6]*/ { if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -42,13 +42,12 @@ } PyDoc_STRVAR(_codecs_encode__doc__, -"encode($module, /, obj, encoding=sys.getdefaultencoding(),\n" -" errors=\'strict\')\n" +"encode($module, /, obj, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" "\n" "Encodes obj using the codec registered for encoding.\n" "\n" -"encoding defaults to the default encoding. errors may be given to set a\n" +"The default encoding is \'utf-8\'. errors may be given to set a\n" "different error handling scheme. Default is \'strict\' meaning that encoding\n" "errors raise a ValueError. Other possible values are \'ignore\', \'replace\'\n" "and \'backslashreplace\' as well as any other name registered with\n" @@ -80,13 +79,12 @@ } PyDoc_STRVAR(_codecs_decode__doc__, -"decode($module, /, obj, encoding=sys.getdefaultencoding(),\n" -" errors=\'strict\')\n" +"decode($module, /, obj, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" "\n" "Decodes obj using the codec registered for encoding.\n" "\n" -"encoding defaults to the default encoding. errors may be given to set a\n" +"Default encoding is \'utf-8\'. errors may be given to set a\n" "different error handling scheme. Default is \'strict\' meaning that encoding\n" "errors raise a ValueError. Other possible values are \'ignore\', \'replace\'\n" "and \'backslashreplace\' as well as any other name registered with\n" @@ -1395,4 +1393,4 @@ #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=713a4081788da1bc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9c9967048027c1c7 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 12:13:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 10:13:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Fixed_doubled_spaces_in_Misc/NEWS=2E?= Message-ID: <20150809101327.94766.52108@psf.io> https://hg.python.org/cpython/rev/4aee29862861 changeset: 97343:4aee29862861 parent: 97339:ad65cad76331 parent: 97342:202a7aabd4fe user: Serhiy Storchaka date: Sun Aug 09 13:12:49 2015 +0300 summary: Fixed doubled spaces in Misc/NEWS. files: Misc/NEWS | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -362,7 +362,7 @@ - Issue #15027: The UTF-32 encoder is now 3x to 7x faster. -- Issue #23290: Optimize set_merge() for cases where the target is empty. +- Issue #23290: Optimize set_merge() for cases where the target is empty. (Contributed by Serhiy Storchaka.) - Issue #2292: PEP 448: Additional Unpacking Generalizations. @@ -917,7 +917,7 @@ unnecessary copying of memoryview in gzip.GzipFile.write(). Original patch by Wolfgang Maier. -- Issue #23252: Added support for writing ZIP files to unseekable streams. +- Issue #23252: Added support for writing ZIP files to unseekable streams. - Issue #23647: Increase impalib's MAXLINE to accommodate modern mailbox sizes. @@ -1638,10 +1638,10 @@ - Issue #21650: Add an `--sort-keys` option to json.tool CLI. -- Issue #22824: Updated reprlib output format for sets to use set literals. +- Issue #22824: Updated reprlib output format for sets to use set literals. Patch contributed by Berker Peksag. -- Issue #22824: Updated reprlib output format for arrays to display empty +- Issue #22824: Updated reprlib output format for arrays to display empty arrays without an unnecessary empty list. Suggested by Serhiy Storchaka. - Issue #22406: Fixed the uu_codec codec incorrectly ported to 3.x. @@ -1980,7 +1980,7 @@ - Issue #21448: Changed FeedParser feed() to avoid O(N**2) behavior when parsing long line. Original patch by Raymond Hettinger. -- Issue #22184: The functools LRU Cache decorator factory now gives an earlier +- Issue #22184: The functools LRU Cache decorator factory now gives an earlier and clearer error message when the user forgets the required parameters. - Issue #17923: glob() patterns ending with a slash no longer match non-dirs on @@ -2155,7 +2155,7 @@ - Issue #21719: Added the ``st_file_attributes`` field to os.stat_result on Windows. -- Issue #21832: Require named tuple inputs to be exact strings. +- Issue #21832: Require named tuple inputs to be exact strings. - Issue #21722: The distutils "upload" command now exits with a non-zero return code when uploading fails. Patch by Martin Dengler. @@ -2213,7 +2213,7 @@ error bubble up as this "bad data" appears in many real world zip files in the wild and is ignored by other zip tools. -- Issue #13742: Added "key" and "reverse" parameters to heapq.merge(). +- Issue #13742: Added "key" and "reverse" parameters to heapq.merge(). (First draft of patch contributed by Simon Sapin.) - Issue #21402: tkinter.ttk now works when default root window is not set. @@ -2244,7 +2244,7 @@ - Issue #21525: Most Tkinter methods which accepted tuples now accept lists too. -- Issue #22166: with the assistance of a new internal _codecs._forget_codec +- Issue #22166: With the assistance of a new internal _codecs._forget_codec helping function, test_codecs now clears the encoding caches to avoid the appearance of a reference leak @@ -2304,7 +2304,7 @@ Decimal.quantize() method in the Python version. It had never been present in the C version. -- Issue #21469: Reduced the risk of false positives in robotparser by +- Issue #21469: Reduced the risk of false positives in robotparser by checking to make sure that robots.txt has been read or does not exist prior to returning True in can_fetch(). @@ -2595,7 +2595,7 @@ - Issue #16233: A module browser (File : Class Browser, Alt+C) requires a editor window with a filename. When Class Browser is requested otherwise, from a shell, output window, or 'Untitled' editor, Idle no longer displays - an error box. It now pops up an Open Module box (Alt+M). If a valid name + an error box. It now pops up an Open Module box (Alt+M). If a valid name is entered and a module is opened, a corresponding browser is also opened. - Issue #4832: Save As to type Python files automatically adds .py to the @@ -3524,7 +3524,7 @@ "{dirname}/clinic/{basename}.h". - Issue #20390: Argument Clinic's "class" directive syntax has been extended - with two new required arguments: "typedef" and "type_object". + with two new required arguments: "typedef" and "type_object". - Issue #20390: Argument Clinic: If __new__ or __init__ functions didn't use kwargs (or args), the PyArg_NoKeywords (or PyArg_NoPositional) calls @@ -4591,10 +4591,10 @@ - Issue #9548: Add a minimal "_bootlocale" module that is imported by the _io module instead of the full locale module. -- Issue #18764: remove the 'print' alias for the PDB 'p' command so that it no +- Issue #18764: Remove the 'print' alias for the PDB 'p' command so that it no longer shadows the print function. -- Issue #19158: a rare race in BoundedSemaphore could allow .release() too +- Issue #19158: A rare race in BoundedSemaphore could allow .release() too often. - Issue #15805: Add contextlib.redirect_stdout(). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 12:13:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 10:13:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Fixed_doubled_spaces_in_Misc/NEWS=2E?= Message-ID: <20150809101327.5517.81852@psf.io> https://hg.python.org/cpython/rev/202a7aabd4fe changeset: 97342:202a7aabd4fe branch: 3.5 parent: 97338:bdd1df816f84 parent: 97341:959168b0c5d4 user: Serhiy Storchaka date: Sun Aug 09 13:11:36 2015 +0300 summary: Fixed doubled spaces in Misc/NEWS. files: Misc/NEWS | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -346,7 +346,7 @@ - Issue #15027: The UTF-32 encoder is now 3x to 7x faster. -- Issue #23290: Optimize set_merge() for cases where the target is empty. +- Issue #23290: Optimize set_merge() for cases where the target is empty. (Contributed by Serhiy Storchaka.) - Issue #2292: PEP 448: Additional Unpacking Generalizations. @@ -901,7 +901,7 @@ unnecessary copying of memoryview in gzip.GzipFile.write(). Original patch by Wolfgang Maier. -- Issue #23252: Added support for writing ZIP files to unseekable streams. +- Issue #23252: Added support for writing ZIP files to unseekable streams. - Issue #23647: Increase impalib's MAXLINE to accommodate modern mailbox sizes. @@ -1622,10 +1622,10 @@ - Issue #21650: Add an `--sort-keys` option to json.tool CLI. -- Issue #22824: Updated reprlib output format for sets to use set literals. +- Issue #22824: Updated reprlib output format for sets to use set literals. Patch contributed by Berker Peksag. -- Issue #22824: Updated reprlib output format for arrays to display empty +- Issue #22824: Updated reprlib output format for arrays to display empty arrays without an unnecessary empty list. Suggested by Serhiy Storchaka. - Issue #22406: Fixed the uu_codec codec incorrectly ported to 3.x. @@ -1964,7 +1964,7 @@ - Issue #21448: Changed FeedParser feed() to avoid O(N**2) behavior when parsing long line. Original patch by Raymond Hettinger. -- Issue #22184: The functools LRU Cache decorator factory now gives an earlier +- Issue #22184: The functools LRU Cache decorator factory now gives an earlier and clearer error message when the user forgets the required parameters. - Issue #17923: glob() patterns ending with a slash no longer match non-dirs on @@ -2139,7 +2139,7 @@ - Issue #21719: Added the ``st_file_attributes`` field to os.stat_result on Windows. -- Issue #21832: Require named tuple inputs to be exact strings. +- Issue #21832: Require named tuple inputs to be exact strings. - Issue #21722: The distutils "upload" command now exits with a non-zero return code when uploading fails. Patch by Martin Dengler. @@ -2197,7 +2197,7 @@ error bubble up as this "bad data" appears in many real world zip files in the wild and is ignored by other zip tools. -- Issue #13742: Added "key" and "reverse" parameters to heapq.merge(). +- Issue #13742: Added "key" and "reverse" parameters to heapq.merge(). (First draft of patch contributed by Simon Sapin.) - Issue #21402: tkinter.ttk now works when default root window is not set. @@ -2228,7 +2228,7 @@ - Issue #21525: Most Tkinter methods which accepted tuples now accept lists too. -- Issue #22166: with the assistance of a new internal _codecs._forget_codec +- Issue #22166: With the assistance of a new internal _codecs._forget_codec helping function, test_codecs now clears the encoding caches to avoid the appearance of a reference leak @@ -2288,7 +2288,7 @@ Decimal.quantize() method in the Python version. It had never been present in the C version. -- Issue #21469: Reduced the risk of false positives in robotparser by +- Issue #21469: Reduced the risk of false positives in robotparser by checking to make sure that robots.txt has been read or does not exist prior to returning True in can_fetch(). @@ -2579,7 +2579,7 @@ - Issue #16233: A module browser (File : Class Browser, Alt+C) requires a editor window with a filename. When Class Browser is requested otherwise, from a shell, output window, or 'Untitled' editor, Idle no longer displays - an error box. It now pops up an Open Module box (Alt+M). If a valid name + an error box. It now pops up an Open Module box (Alt+M). If a valid name is entered and a module is opened, a corresponding browser is also opened. - Issue #4832: Save As to type Python files automatically adds .py to the @@ -3508,7 +3508,7 @@ "{dirname}/clinic/{basename}.h". - Issue #20390: Argument Clinic's "class" directive syntax has been extended - with two new required arguments: "typedef" and "type_object". + with two new required arguments: "typedef" and "type_object". - Issue #20390: Argument Clinic: If __new__ or __init__ functions didn't use kwargs (or args), the PyArg_NoKeywords (or PyArg_NoPositional) calls @@ -4575,10 +4575,10 @@ - Issue #9548: Add a minimal "_bootlocale" module that is imported by the _io module instead of the full locale module. -- Issue #18764: remove the 'print' alias for the PDB 'p' command so that it no +- Issue #18764: Remove the 'print' alias for the PDB 'p' command so that it no longer shadows the print function. -- Issue #19158: a rare race in BoundedSemaphore could allow .release() too +- Issue #19158: A rare race in BoundedSemaphore could allow .release() too often. - Issue #15805: Add contextlib.redirect_stdout(). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 12:13:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 10:13:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_doubled_?= =?utf-8?q?spaces_in_Misc/NEWS=2E?= Message-ID: <20150809101327.17731.2100@psf.io> https://hg.python.org/cpython/rev/959168b0c5d4 changeset: 97341:959168b0c5d4 branch: 3.4 parent: 97334:56f4327d3c57 user: Serhiy Storchaka date: Sun Aug 09 13:07:18 2015 +0300 summary: Fixed doubled spaces in Misc/NEWS. files: Misc/NEWS | 36 ++++++++++++++++++------------------ 1 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,7 +32,7 @@ - Issue #24102: Fixed exception type checking in standard error handlers. -- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API when the data was a list subclass. - Issue #24407: Fix crash when dict is mutated while being updated. @@ -758,7 +758,7 @@ - Issue #16233: A module browser (File : Class Browser, Alt+C) requires a editor window with a filename. When Class Browser is requested otherwise, from a shell, output window, or 'Untitled' editor, Idle no longer displays - an error box. It now pops up an Open Module box (Alt+M). If a valid name + an error box. It now pops up an Open Module box (Alt+M). If a valid name is entered and a module is opened, a corresponding browser is also opened. - Issue #4832: Save As to type Python files automatically adds .py to the @@ -1009,7 +1009,7 @@ - Issue #21448: Changed FeedParser feed() to avoid O(N**2) behavior when parsing long line. Original patch by Raymond Hettinger. -- Issue #22184: The functools LRU Cache decorator factory now gives an earlier +- Issue #22184: The functools LRU Cache decorator factory now gives an earlier and clearer error message when the user forgets the required parameters. - Issue #17923: glob() patterns ending with a slash no longer match non-dirs on @@ -1051,7 +1051,7 @@ - Issue #21044: tarfile.open() now handles fileobj with an integer 'name' attribute. Based on patch by Antoine Pietri. -- Issue #21867: Prevent turtle crash due to invalid undo buffer size. +- Issue #21867: Prevent turtle crash due to invalid undo buffer size. - Issue #19076: Don't pass the redundant 'file' argument to self.error(). @@ -1097,16 +1097,16 @@ - Issue #21491: socketserver: Fix a race condition in child processes reaping. -- Issue #21832: Require named tuple inputs to be exact strings. - -- Issue #19145: The times argument for itertools.repeat now handles +- Issue #21832: Require named tuple inputs to be exact strings. + +- Issue #19145: The times argument for itertools.repeat now handles negative values the same way for keyword arguments as it does for positional arguments. - Issue #21812: turtle.shapetransform did not tranform the turtle on the first call. (Issue identified and fixed by Lita Cho.) -- Issue #21635: The difflib SequenceMatcher.get_matching_blocks() method +- Issue #21635: The difflib SequenceMatcher.get_matching_blocks() method cache didn't match the actual result. The former was a list of tuples and the latter was a list of named tuples. @@ -1167,7 +1167,7 @@ - Issue #14710: pkgutil.find_loader() no longer raises an exception when a module doesn't exist. -- Issue #21481: Argparse equality and inequality tests now return +- Issue #21481: Argparse equality and inequality tests now return NotImplemented when comparing to an unknown type. - Issue #8743: Fix interoperability between set objects and the @@ -1253,7 +1253,7 @@ Tests ----- -- Issue #22166: with the assistance of a new internal _codecs._forget_codec +- Issue #22166: With the assistance of a new internal _codecs._forget_codec helping function, test_codecs now clears the encoding caches to avoid the appearance of a reference leak @@ -1425,7 +1425,7 @@ - Issue #21088: Bugfix for curses.window.addch() regression in 3.4.0. In porting to Argument Clinic, the first two arguments were reversed. -- Issue #21469: Reduced the risk of false positives in robotparser by +- Issue #21469: Reduced the risk of false positives in robotparser by checking to make sure that robots.txt has been read or does not exist prior to returning True in can_fetch(). @@ -2244,7 +2244,7 @@ "{dirname}/clinic/{basename}.h". - Issue #20390: Argument Clinic's "class" directive syntax has been extended - with two new required arguments: "typedef" and "type_object". + with two new required arguments: "typedef" and "type_object". - Issue #20390: Argument Clinic: If __new__ or __init__ functions didn't use kwargs (or args), the PyArg_NoKeywords (or PyArg_NoPositional) calls @@ -3311,10 +3311,10 @@ - Issue #9548: Add a minimal "_bootlocale" module that is imported by the _io module instead of the full locale module. -- Issue #18764: remove the 'print' alias for the PDB 'p' command so that it no +- Issue #18764: Remove the 'print' alias for the PDB 'p' command so that it no longer shadows the print function. -- Issue #19158: a rare race in BoundedSemaphore could allow .release() too +- Issue #19158: A rare race in BoundedSemaphore could allow .release() too often. - Issue #15805: Add contextlib.redirect_stdout(). @@ -7935,7 +7935,7 @@ and bytearray.split may now be passed as keyword arguments. - Issue #13012: The 'keepends' parameter to str.splitlines may now be passed - as a keyword argument: "my_string.splitlines(keepends=True)". The same + as a keyword argument: "my_string.splitlines(keepends=True)". The same change also applies to bytes.splitlines and bytearray.splitlines. - Issue #7732: Don't open a directory as a file anymore while importing a @@ -8926,7 +8926,7 @@ of the text mode (using the locale encoding) to avoid encoding issues. - Issue #12147: Adjust the new-in-3.2 smtplib.send_message method for better - conformance to the RFCs: correctly handle Sender and Resent- headers. + conformance to the RFCs: correctly handle Sender and Resent- headers. - Issue #12352: Fix a deadlock in multiprocessing.Heap when a block is freed by the garbage collector while the Heap lock is held. @@ -9330,7 +9330,7 @@ multipart subparts with an 8-bit CTE into unicode instead of preserving the bytes. -- Issue #1690608: email.util.formataddr is now RFC 2047 aware: it now has a +- Issue #1690608: email.util.formataddr is now RFC 2047 aware: it now has a charset parameter that defaults to utf-8 and is used as the charset for RFC 2047 encoding when the realname contains non-ASCII characters. @@ -9925,7 +9925,7 @@ Patch by Garrett Cooper. - Issue #10736: Fix test_ttk test_widgets failures with Cocoa Tk 8.5.9 - 2.8 + on Mac OS X. (Patch by Ronald Oussoren) + 2.8+ on Mac OS X. (Patch by Ronald Oussoren) - Issue #12057: Add tests for ISO 2022 codecs (iso2022_jp, iso2022_jp_2, iso2022_kr). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 12:13:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 10:13:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_doubled_?= =?utf-8?q?spaces_in_Misc/NEWS=2E?= Message-ID: <20150809101327.41831.96318@psf.io> https://hg.python.org/cpython/rev/089f1a23dfac changeset: 97340:089f1a23dfac branch: 2.7 parent: 97333:7d69b214e668 user: Serhiy Storchaka date: Sun Aug 09 13:07:06 2015 +0300 summary: Fixed doubled spaces in Misc/NEWS. files: Misc/NEWS | 52 +++++++++++++++++++++--------------------- 1 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -99,7 +99,7 @@ - Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. -- Issue #24286: Dict view were not registered with the MappingView abstract +- Issue #24286: Dict view were not registered with the MappingView abstract base classes. This caused key and item views in OrderedDict to not be equal to their regular dict counterparts. @@ -178,9 +178,9 @@ Core and Builtins ----------------- -- Issue #23971: Fix underestimated presizing in dict.fromkeys(). - -- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API +- Issue #23971: Fix underestimated presizing in dict.fromkeys(). + +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API when the data was a list subclass. - Issue #23629: Fix the default __sizeof__ implementation for variable-sized @@ -771,7 +771,7 @@ - Issue #16233: A module browser (File : Class Browser, Alt+C) requires a editor window with a filename. When Class Browser is requested otherwise, from a shell, output window, or 'Untitled' editor, Idle no longer displays - an error box. It now pops up an Open Module box (Alt+M). If a valid name + an error box. It now pops up an Open Module box (Alt+M). If a valid name is entered and a module is opened, a corresponding browser is also opened. - Issue #4832: Save As to type Python files automatically adds .py to the @@ -909,18 +909,18 @@ - Issue #21672: Fix the behavior of ntpath.join on UNC-style paths. -- Issue #19145: The times argument for itertools.repeat now handles +- Issue #19145: The times argument for itertools.repeat now handles negative values the same way for keyword arguments as it does for positional arguments. -- Issue #21832: Require named tuple inputs to be exact strings. - -- Issue #8343: Named group error messages in the re module did not show +- Issue #21832: Require named tuple inputs to be exact strings. + +- Issue #8343: Named group error messages in the re module did not show the name of the erroneous group. - Issue #21491: SocketServer: Fix a race condition in child processes reaping. -- Issue #21635: The difflib SequenceMatcher.get_matching_blocks() method +- Issue #21635: The difflib SequenceMatcher.get_matching_blocks() method cache didn't match the actual result. The former was a list of tuples and the latter was a list of named tuples. @@ -957,7 +957,7 @@ - Issue #8743: Fix interoperability between set objects and the collections.Set() abstract base class. -- Issue #21481: Argparse equality and inequality tests now return +- Issue #21481: Argparse equality and inequality tests now return NotImplemented when comparing to an unknown type. IDLE @@ -1099,7 +1099,7 @@ - Issue #21470: Do a better job seeding the random number generator by using enough bytes to span the full state space of the Mersenne Twister. -- Issue #21469: Reduced the risk of false positives in robotparser by +- Issue #21469: Reduced the risk of false positives in robotparser by checking to make sure that robots.txt has been read or does not exist prior to returning True in can_fetch(). @@ -1596,7 +1596,7 @@ - Issue #19131: The aifc module now correctly reads and writes sampwidth of compressed streams. -- Issue #19158: a rare race in BoundedSemaphore could allow .release() too +- Issue #19158: A rare race in BoundedSemaphore could allow .release() too often. - Issue #18037: 2to3 now escapes '\u' and '\U' in native strings. @@ -3597,7 +3597,7 @@ greater or equal to the default value, the value with which the interpreter was built. -- Issue #11802: The cache in filecmp now has a maximum size of 100 so that +- Issue #11802: The cache in filecmp now has a maximum size of 100 so that it won't grow without bound. - Issue #12404: Remove C89 incompatible code from mmap module. Patch by Akira @@ -3983,7 +3983,7 @@ - Issue #11277: mmap.mmap() calls fcntl(fd, F_FULLFSYNC) on Mac OS X to get around a mmap bug with sparse files. Patch written by Steffen Daode Nurpmeso. -- Issue #10761: Fix tarfile.extractall failure when symlinked files are +- Issue #10761: Fix tarfile.extractall failure when symlinked files are present. Initial patch by Scott Leerssen. - Issue #11763: don't use difflib in TestCase.assertMultiLineEqual if the @@ -4494,7 +4494,7 @@ - Issue #8530: Prevent stringlib fastsearch from reading beyond the front of an array. -- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe. +- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe. - Issue #9416: Fix some issues with complex formatting where the output with no type specifier failed to match the str output: @@ -4891,7 +4891,7 @@ os.getgroups() can now return more than 16 groups on MacOSX. - Issue #9277: Fix bug in struct.pack for bools in standard mode - (e.g., struct.pack('>?')): if conversion to bool raised an exception + (e.g., struct.pack('>?')): if conversion to bool raised an exception then that exception wasn't properly propagated on machines where char is unsigned. @@ -4939,7 +4939,7 @@ - Issue #9275: The OSX installer once again installs links to binaries in ``/usr/local/bin``. -- Issue #9392: A framework build on OSX will once again use a versioned name +- Issue #9392: A framework build on OSX will once again use a versioned name of the ``2to3`` tool, that is you can use ``2to3-2.7`` to select the Python 2.7 edition of 2to3. @@ -6898,7 +6898,7 @@ - Issue #6851: Fix urllib.urlopen crash on secondairy threads on OSX 10.6 -- Issue #4606: Passing 'None' if ctypes argtype is set to POINTER(...) does now +- Issue #4606: Passing 'None' if ctypes argtype is set to POINTER(...) does now always result in NULL. - Issue #5042: ctypes Structure sub-subclass does now initialize correctly with @@ -7743,7 +7743,7 @@ wasn't working with file paths containing spaces. - Issue #5783: Windows: Version string for the .chm help file changed, - file not being accessed Patch by Guilherme Polo/ + file not being accessed. Patch by Guilherme Polo/ - Issue #1529142: Allow multiple IDLE GUI/subprocess pairs to exist simultaneously. Thanks to David Scherer for suggesting the use of an @@ -8439,7 +8439,7 @@ - Issue #3437: Bug fix in robotparser parsing of Allow: lines. -- Issue #1592: Improve error reporting when operations are attempted +- Issue #1592: Improve error reporting when operations are attempted on a closed shelf. - Deprecate the "ast" parser function aliases. @@ -8661,7 +8661,7 @@ - Add future_builtins.ascii(). -- Several set methods now accept multiple arguments: update(), union(), +- Several set methods now accept multiple arguments: update(), union(), intersection(), intersection_update(), difference(), and difference_update(). - Issue #2898: Added sys.getsizeof() to retrieve size of objects in bytes. @@ -8697,7 +8697,7 @@ ----------------- - Issue #1179: [CVE-2007-4965] Integer overflow in imageop module. -- Issue #3116: marshal.dumps() had quadratic behavior for strings > 32Mb. +- Issue #3116: marshal.dumps() had quadratic behavior for strings > 32Mb. - Issue #2138: Add factorial() to the math module. @@ -9679,9 +9679,9 @@ - When __slots__ are set to a unicode string, make it work the same as setting a plain string, ie don't expand to single letter identifiers. -- Request #1191699: Slices can now be pickled. - -- Request #1193128: str.translate() now allows a None argument for +- Request #1191699: Slices can now be pickled. + +- Request #1193128: str.translate() now allows a None argument for translations that only remove characters without re-mapping the remaining characters. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 12:34:42 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 10:34:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_section_for_3=2E5=2E?= =?utf-8?q?0rc1_in_Misc/NEWS_and_moved_relevant_entities_to_it=2E?= Message-ID: <20150809103442.110764.17925@psf.io> https://hg.python.org/cpython/rev/42e2e67b8e6f changeset: 97344:42e2e67b8e6f user: Serhiy Storchaka date: Sun Aug 09 13:33:51 2015 +0300 summary: Added section for 3.5.0rc1 in Misc/NEWS and moved relevant entities to it. files: Misc/NEWS | 83 ++++++++++++++++++++++++++++-------------- 1 files changed, 55 insertions(+), 28 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,14 +10,62 @@ Core and Builtins ----------------- -- Issue #24667: Resize odict in all cases that the underlying dict resizes. - Library ------- +- Issue #24360: Improve __repr__ of argparse.Namespace() for invalid + identifiers. Patch by Matthias Bussonnier. + +- Issue #23426: run_setup was broken in distutils. + Patch from Alexander Belopolsky. + +- Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. + +- Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can + only be used with 'r'. Patch from Jeff Balogh and John O'Connor. + +- Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. + +- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. + Patch from Nicola Palumbo and Laurent De Buyst. + +- Issue #24426: Fast searching optimization in regular expressions now works + for patterns that starts with capturing groups. Fast searching optimization + now can't be disabled at compile time. + +- Issue #23661: unittest.mock side_effects can now be exceptions again. This + was a regression vs Python 3.4. Patch from Ignacio Rossi + +- Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo + functions. + +Documentation +------------- + +Tests +----- + + +What's New in Python 3.5.0 release candidate 1? +=============================================== + +Release date: 2015-08-09 + +Core and Builtins +----------------- + +- Issue #24667: Resize odict in all cases that the underlying dict resizes. + +Library +------- + - Issue #24824: Signatures of codecs.encode() and codecs.decode() now are compatible with pydoc. +- Issue #24634: Importing uuid should not try to load libc on Windows + +- Issue #24798: _msvccompiler.py doesn't properly support manifests + - Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. @@ -38,41 +86,20 @@ - Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. -- Issue #24360: Improve __repr__ of argparse.Namespace() for invalid - identifiers. Patch by Matthias Bussonnier. - - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. -- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. -- Issue #23426: run_setup was broken in distutils. - Patch from Alexander Belopolsky. +- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. -- Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. - -- Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can - only be used with 'r'. Patch from Jeff Balogh and John O'Connor. - -- Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. - -- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. - Patch from Nicola Palumbo and Laurent De Buyst. - -- Issue #24426: Fast searching optimization in regular expressions now works - for patterns that starts with capturing groups. Fast searching optimization - now can't be disabled at compile time. - -- Issue #23661: unittest.mock side_effects can now be exceptions again. This - was a regression vs Python 3.4. Patch from Ignacio Rossi - -- Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo - functions. +- Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. + Patch by Gustavo J. A. M. Carneiro. + +- Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 12:45:52 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 09 Aug 2015 10:45:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_changeset_42e2e?= =?utf-8?q?67b8e6f?= Message-ID: <20150809104552.53971.94809@psf.io> https://hg.python.org/cpython/rev/a16c6456f34b changeset: 97345:a16c6456f34b user: Serhiy Storchaka date: Sun Aug 09 13:44:04 2015 +0300 summary: Backed out changeset 42e2e67b8e6f files: Misc/NEWS | 97 +++++++++++++++--------------------------- 1 files changed, 35 insertions(+), 62 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,15 +10,50 @@ Core and Builtins ----------------- +- Issue #24667: Resize odict in all cases that the underlying dict resizes. + Library ------- +- Issue #24824: Signatures of codecs.encode() and codecs.decode() now are + compatible with pydoc. + +- Issue #4395: Better testing and documentation of binary operators. + Patch by Martin Panter. + +- Issue #23973: Update typing.py from GitHub repo. + +- Issue #23004: mock_open() now reads binary data correctly when the type of + read_data is bytes. Initial patch by Aaron Hill. + +- Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. + +- Issue #23652: Make it possible to compile the select module against the + libc headers from the Linux Standard Base, which do not include some + EPOLL macros. Patch by Matt Frank. + +- Issue #22932: Fix timezones in email.utils.formatdate. + Patch from Dmitry Shachnev. + +- Issue #23779: imaplib raises TypeError if authenticator tries to abort. + Patch from Craig Holmquist. + - Issue #24360: Improve __repr__ of argparse.Namespace() for invalid identifiers. Patch by Matthias Bussonnier. +- Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch + written by Matthieu Gautier. + +- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. + +- Issue #23254: Document how to close the TCPServer listening socket. + Patch from Martin Panter. + - Issue #23426: run_setup was broken in distutils. Patch from Alexander Belopolsky. +- Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. + - Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. - Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can @@ -42,68 +77,6 @@ Documentation ------------- -Tests ------ - - -What's New in Python 3.5.0 release candidate 1? -=============================================== - -Release date: 2015-08-09 - -Core and Builtins ------------------ - -- Issue #24667: Resize odict in all cases that the underlying dict resizes. - -Library -------- - -- Issue #24824: Signatures of codecs.encode() and codecs.decode() now are - compatible with pydoc. - -- Issue #24634: Importing uuid should not try to load libc on Windows - -- Issue #24798: _msvccompiler.py doesn't properly support manifests - -- Issue #4395: Better testing and documentation of binary operators. - Patch by Martin Panter. - -- Issue #23973: Update typing.py from GitHub repo. - -- Issue #23004: mock_open() now reads binary data correctly when the type of - read_data is bytes. Initial patch by Aaron Hill. - -- Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. - -- Issue #23652: Make it possible to compile the select module against the - libc headers from the Linux Standard Base, which do not include some - EPOLL macros. Patch by Matt Frank. - -- Issue #22932: Fix timezones in email.utils.formatdate. - Patch from Dmitry Shachnev. - -- Issue #23779: imaplib raises TypeError if authenticator tries to abort. - Patch from Craig Holmquist. - -- Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch - written by Matthieu Gautier. - -- Issue #23254: Document how to close the TCPServer listening socket. - Patch from Martin Panter. - -- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - -- Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. - -- Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. - Patch by Gustavo J. A. M. Carneiro. - -- Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. - -Documentation -------------- - - Issue #24129: Clarify the reference documentation for name resolution. This includes removing the assumption that readers will be familiar with the name resolution scheme Python used prior to the introduction of lexical -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 9 23:08:18 2015 From: python-checkins at python.org (eric.smith) Date: Sun, 09 Aug 2015 21:08:18 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_code_typos=2E_Minor_rew?= =?utf-8?q?ording=2E?= Message-ID: <20150809210818.111014.94364@psf.io> https://hg.python.org/peps/rev/d3695d3fc321 changeset: 5944:d3695d3fc321 user: Eric V. Smith date: Sun Aug 09 17:08:17 2015 -0400 summary: Fixed code typos. Minor rewording. files: pep-0498.txt | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -306,18 +306,18 @@ Because expressions may begin with a left brace ('{'), there is a problem when parsing such expressions. For example:: - >>> f'{{k:v for k, v in [(1, 2), (3, 4)}}' - '{k:v for k, v in [(1, 2), (3, 4)}' + >>> f'{{k:v for k, v in [(1, 2), (3, 4)]}}' + '{k:v for k, v in [(1, 2), (3, 4)]}' In this case, the doubled left braces and doubled right braces are interpreted as single braces, and the string becomes just a normal string literal. There is no expression evaluation being performed. -To account for this, whitespace characters at the beginning of an -expression are skipped:: +To allow for expressions to begin with a left brace, whitespace +characters at the beginning of an expression are skipped:: - >>> f'{ {k:v for k, v in [(1, 2), (3, 4)}}' - '{k:v for k, v in [(1, 2), (3, 4)}' + >>> f'{ {k:v for k, v in [(1, 2), (3, 4)]}}' + '{1: 2, 3: 4}' Discussion ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 9 23:53:45 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 09 Aug 2015 21:53:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320059=3A_urllib?= =?utf-8?q?=2Eparse_raises_ValueError_on_all_invalid_ports=2E?= Message-ID: <20150809215345.23392.94424@psf.io> https://hg.python.org/cpython/rev/7c78279afc30 changeset: 97346:7c78279afc30 user: Robert Collins date: Mon Aug 10 09:53:30 2015 +1200 summary: Issue #20059: urllib.parse raises ValueError on all invalid ports. Patch by Martin Panter. files: Doc/library/urllib.parse.rst | 18 +++++++++-- Doc/whatsnew/3.6.rst | 5 ++- Lib/test/test_urlparse.py | 36 +++++++++++------------ Lib/urllib/parse.py | 3 +- Misc/NEWS | 3 ++ 5 files changed, 39 insertions(+), 26 deletions(-) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -115,8 +115,9 @@ | | | if present | | +------------------+-------+--------------------------+----------------------+ - See section :ref:`urlparse-result-object` for more information on the result - object. + Reading the :attr:`port` attribute will raise a :exc:`ValueError` if + an invalid port is specified in the URL. See section + :ref:`urlparse-result-object` for more information on the result object. .. versionchanged:: 3.2 Added IPv6 URL parsing capabilities. @@ -126,6 +127,10 @@ false), in accordance with :rfc:`3986`. Previously, a whitelist of schemes that support fragments existed. + .. versionchanged:: 3.6 + Out-of-range port numbers now raise :exc:`ValueError`, instead of + returning :const:`None`. + .. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace') @@ -228,8 +233,13 @@ | | | if present | | +------------------+-------+-------------------------+----------------------+ - See section :ref:`urlparse-result-object` for more information on the result - object. + Reading the :attr:`port` attribute will raise a :exc:`ValueError` if + an invalid port is specified in the URL. See section + :ref:`urlparse-result-object` for more information on the result object. + + .. versionchanged:: 3.6 + Out-of-range port numbers now raise :exc:`ValueError`, instead of + returning :const:`None`. .. function:: urlunsplit(parts) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -162,7 +162,10 @@ Changes in the Python API ------------------------- -* None yet. +* Reading the :attr:`~urllib.parse.SplitResult.port` attribute of + :func:`urllib.parse.urlsplit` and :func:`~urllib.parse.urlparse` results + now raises :exc:`ValueError` for out-of-range values, rather than + returning :const:`None`. See :issue:`20059`. Changes in the C API diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -554,29 +554,27 @@ self.assertEqual(p.port, 80) self.assertEqual(p.geturl(), url) - # Verify an illegal port is returned as None + # Verify an illegal port raises ValueError url = b"HTTP://WWW.PYTHON.ORG:65536/doc/#frag" p = urllib.parse.urlsplit(url) - self.assertEqual(p.port, None) + with self.assertRaisesRegex(ValueError, "out of range"): + p.port def test_attributes_bad_port(self): - """Check handling of non-integer ports.""" - p = urllib.parse.urlsplit("http://www.example.net:foo") - self.assertEqual(p.netloc, "www.example.net:foo") - self.assertRaises(ValueError, lambda: p.port) - - p = urllib.parse.urlparse("http://www.example.net:foo") - self.assertEqual(p.netloc, "www.example.net:foo") - self.assertRaises(ValueError, lambda: p.port) - - # Once again, repeat ourselves to test bytes - p = urllib.parse.urlsplit(b"http://www.example.net:foo") - self.assertEqual(p.netloc, b"www.example.net:foo") - self.assertRaises(ValueError, lambda: p.port) - - p = urllib.parse.urlparse(b"http://www.example.net:foo") - self.assertEqual(p.netloc, b"www.example.net:foo") - self.assertRaises(ValueError, lambda: p.port) + """Check handling of invalid ports.""" + for bytes in (False, True): + for parse in (urllib.parse.urlsplit, urllib.parse.urlparse): + for port in ("foo", "1.5", "-1", "0x10"): + with self.subTest(bytes=bytes, parse=parse, port=port): + netloc = "www.example.net:" + port + url = "http://" + netloc + if bytes: + netloc = netloc.encode("ascii") + url = url.encode("ascii") + p = parse(url) + self.assertEqual(p.netloc, netloc) + with self.assertRaises(ValueError): + p.port def test_attributes_without_netloc(self): # This example is straight from RFC 3261. It looks like it diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -156,9 +156,8 @@ port = self._hostinfo[1] if port is not None: port = int(port, 10) - # Return None on an illegal port if not ( 0 <= port <= 65535): - return None + raise ValueError("Port out of range 0-65535") return port diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #20059: urllib.parse raises ValueError on all invalid ports. + Patch by Martin Panter. + - Issue #24824: Signatures of codecs.encode() and codecs.decode() now are compatible with pydoc. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 10 00:22:40 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 09 Aug 2015 22:22:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZXMgIzI0ODM1LCAjMjQ3NjMp?= Message-ID: <20150809222240.5517.59871@psf.io> https://hg.python.org/cpython/rev/f304ba9425a3 changeset: 97349:f304ba9425a3 parent: 97346:7c78279afc30 parent: 97348:aa527ee0d27f user: Yury Selivanov date: Sun Aug 09 18:22:11 2015 -0400 summary: Merge 3.5 (issues #24835, #24763) files: Lib/test/test_asyncio/test_subprocess.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 10 00:22:40 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 09 Aug 2015 22:22:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28issues_=2324835=2C_=2324763=29?= Message-ID: <20150809222240.23398.94494@psf.io> https://hg.python.org/cpython/rev/aa527ee0d27f changeset: 97348:aa527ee0d27f branch: 3.5 parent: 97342:202a7aabd4fe parent: 97347:2648dddd3248 user: Yury Selivanov date: Sun Aug 09 18:21:58 2015 -0400 summary: Merge 3.4 (issues #24835, #24763) files: Lib/test/test_asyncio/test_subprocess.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 10 00:22:40 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 09 Aug 2015 22:22:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0NzYz?= =?utf-8?q?=3A_Fix_asyncio_test_on_Windows_=28fix_reverted_change=29?= Message-ID: <20150809222240.23400.20484@psf.io> https://hg.python.org/cpython/rev/2648dddd3248 changeset: 97347:2648dddd3248 branch: 3.4 parent: 97341:959168b0c5d4 user: Yury Selivanov date: Sun Aug 09 18:21:25 2015 -0400 summary: Issue #24763: Fix asyncio test on Windows (fix reverted change) See also issue #24835 files: Lib/test/test_asyncio/test_subprocess.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 10 01:51:51 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 09 Aug 2015 23:51:51 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Updated=09PEP_495=3A?= Message-ID: <20150809235151.5517.45237@psf.io> https://hg.python.org/peps/rev/2b74b0189b83 changeset: 5945:2b74b0189b83 user: Alexander Belopolsky date: Sun Aug 09 19:51:45 2015 -0400 summary: Updated PEP 495: * Explained creation of invalid instances. * Added "Combining and splitting date and time" section. * Clarified that fromutc() will not change. * Removed a paragraph listing methods that can produce first=False. * Corrected spelling mistakes. files: pep-0495.txt | 60 ++++++++++++++++++++++++++++------------ 1 files changed, 42 insertions(+), 18 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -29,7 +29,7 @@ ========= In the most world locations there have been and will be times when -local clocks are moved back. In those times intervals are introduced +local clocks are moved back. In those times, intervals are introduced in which local clocks show the same time twice in the same day. In these situations, the information displayed on a local clock (or stored in a Python datetime instance) is insufficient to identify a @@ -47,7 +47,18 @@ of ``datetime.time`` and ``datetime.datetime`` classes. This member should have the value True for all instances except those that represent the second (chronologically) moment in time in an ambiguous -case. +case. [#]_ + +.. [#] An instance that has ``first=False`` in a non-ambiguous case is + said to represent an invalid time (or is invalid for short), but + users are not prevented from creating invalid instances by passing + ``first=False`` to a constructor or to a ``replace()`` method. This + is similar to the current situation with the instances that fall in + the spring-forward gap. Such instances don't represent any valid + time, but neither the constructors nor the ``replace()`` methods + check whether the instances that they produce are valid. Moreover, + this PEP specifies how various functions should behave when given an + invalid instance. Affected APIs ------------- @@ -72,8 +83,8 @@ The ``replace()`` methods of the ``datetime.time`` and ``datetime.datetime`` classes will get a new keyword-only argument -called ``first`` with the default value ``True``. It will -becave similarly to the other ``replace()`` arguments: if the ``first`` +called ``first``. It will +behave similarly to the other ``replace()`` arguments: if the ``first`` argument is specified and given a boolean value, the new instance returned by ``replace()`` will have its ``first`` attribute set to that value. In CPython, a non-boolean value of ``first`` will @@ -165,6 +176,16 @@ datetime.datetime(2014, 11, 2, 1, 30, first=False) +Combining and splitting date and time +..................................... + +The ``datetime.datetime.combine`` method will copy the value of the +``first`` attribute to the resulting ``datetime.datetime`` instance. + +The ``datetime.datetime.time`` method will copy the value of the +``first`` attribute to the resulting ``datetime.time`` instance. + + Implementations of tzinfo in stdlib ................................... @@ -174,6 +195,12 @@ implementation will return the same constant value as they do now regardless of the value of ``first``. +The basic implementation of ``fromutc()`` in the abstract +``datetime.tzinfo`` class, will not change. It is currently not +used anywhere in the stdlib because the only included ``tzinfo`` +implementation (the ``datetime.timzeone`` class implementing fixed +offset timezones) override ``fromutc()``. + New guidelines will be published for implementing concrete timezones with variable UTC offset. @@ -185,11 +212,11 @@ support variable UTC offsets (due to DST and other causes) must follow these guidelines. -New subclasses should override the baseclass ``fromutc()`` method so -that in all cases where two UTC times ``u1`` and ``u2`` (``u1`` <``u2``) -corespond to the same local time ``fromutc(u1)`` will return an instance -with ``first=True`` and ``fromutc(u1)`` will return an instance -with ``first=False``. +New subclasses must override the base-class ``fromutc()`` method +and implement it so that in all cases where two UTC times ``u1`` +and ``u2`` (``u1`` <``u2``) correspond to the same local time +``fromutc(u1)`` will return an instance with ``first=True`` and +``fromutc(u2)`` will return an instance with ``first=False``. New implementations of ``utcoffset()`` and ``dst()`` methods should ignore the value of ``first`` unless they are called on the ambiguous @@ -259,20 +286,17 @@ -------------------- The value of "first" will be ignored in all operations except those -that involve conversion between timezones. [#]_ +that involve conversion between timezones. [#]_ As a consequence, +`datetime.datetime`` or ``datetime.time`` instances that differ only +by the value of ``first`` will compare as equal. Applications that +need to differentiate between such instances should check the value of +``first`` or convert them to a timezone that does not have ambiguous +times. The result of addition (subtraction) of a timedelta to (from) a datetime will always have ``first`` set to ``True`` even if the original datetime instance had ``first=False``. -(The only methods that will be able to produce non-default value of -"first" are ``__new__``, and ``replace()`` methods of the -``datetime.datetime`` and ``datetime.time`` classes ``now()``, -``astimezone()`` and ``fromtimestamp()`` methods of the -``datetime.datetime`` class, and ``fromutc()`` method of some tzinfo -implementations.) - - .. [#] As of Python 3.5, ``tzinfo`` is ignored whenever timedelta is added or subtracted from a ``datetime.datetime`` instance or when one ``datetime.datetime`` instance is subtracted from another with -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 10 02:03:03 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 10 Aug 2015 00:03:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Corrected_tables_m?= =?utf-8?q?arkup=2E?= Message-ID: <20150810000303.41851.44158@psf.io> https://hg.python.org/peps/rev/f5b3795f1b70 changeset: 5946:f5b3795f1b70 user: Alexander Belopolsky date: Sun Aug 09 20:02:58 2015 -0400 summary: PEP 495: Corrected tables markup. files: pep-0495.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -227,7 +227,7 @@ +-----------------+----------------+------------------+ | | first=True | first=False | -+-----------------+----------------+------------------+ ++=================+================+==================+ | utcoff() | stdoff + hour | stdoff | +-----------------+----------------+------------------+ | dst() | hour | zero | @@ -242,7 +242,7 @@ +-----------------+----------------+------------------+ | | first=True | first=False | -+-----------------+----------------+------------------+ ++=================+================+==================+ | utcoff() | stdoff | stdoff + hour | +-----------------+----------------+------------------+ | dst() | zero | hour | @@ -256,7 +256,7 @@ +-----------------+----------------+-----------------------------+ | | first=True | first=False | -+-----------------+----------------+-----------------------------+ ++=================+================+=============================+ | ambiguous | oldoff | newoff = oldoff - delta | +-----------------+----------------+-----------------------------+ | invalid | oldoff | newoff = oldoff + delta | -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 10 02:05:52 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 10 Aug 2015 00:05:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Removed_a_separate?= =?utf-8?q?_=27Comparison=27_section=2E?= Message-ID: <20150810000552.41827.35534@psf.io> https://hg.python.org/peps/rev/74ac5a41d0fc changeset: 5947:74ac5a41d0fc user: Alexander Belopolsky date: Sun Aug 09 20:05:46 2015 -0400 summary: PEP 495: Removed a separate 'Comparison' section. files: pep-0495.txt | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -303,13 +303,6 @@ the same (even not-None) ``tzinfo``. This may change in the future, but such changes are outside of the scope of this PEP. -Comparison ----------- - -Instances of ``datetime.time`` and ``datetime.datetime`` classes that -differ only by the value of their ``first`` attribute will compare as -equal. - Backward and Forward Compatibility ---------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 10 02:33:21 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 10 Aug 2015 00:33:21 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_=27Treminology=27_?= =?utf-8?q?section_and_minor_edits=2E?= Message-ID: <20150810003321.17735.45581@psf.io> https://hg.python.org/peps/rev/0f11deecc9f8 changeset: 5948:0f11deecc9f8 user: Alexander Belopolsky date: Sun Aug 09 20:33:18 2015 -0400 summary: PEP 495: 'Treminology' section and minor edits. files: pep-0495.txt | 39 +++++++++++++++++++++++++-------------- 1 files changed, 25 insertions(+), 14 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -37,6 +37,16 @@ flag to the ``datetime`` instances that will distinguish between the two ambiguous times. + +Terminology +=========== + +When clocks are moved back, we say that a *fold* is created in the +fabric of time. When the clock are moved forward, a *gap* is created. +A local time that falls in the fold is called *ambiguous*. A local +time that falls in the gap is called *missing*. + + Proposal ======== @@ -118,7 +128,7 @@ The ``timestamp()`` method of ``datetime.datetime`` will return different values for ``datetime.datetime`` instances that differ only by the value of their ``first`` attribute if and only if these instances represent an -ambiguous or a non-existent value. +ambiguous or a non-existent time. When a ``datetime.datetime`` instance ``dt`` represents an ambiguous (repeated) time, there are two values ``s0`` and ``s1`` such that:: @@ -137,7 +147,7 @@ 1414909800.0 -When a ``datetime.datetime`` instance ``dt`` represents an invalid +When a ``datetime.datetime`` instance ``dt`` represents a missing time, there is no value ``s`` for which:: datetime.fromtimestamp(s) == dt @@ -149,7 +159,7 @@ other is the similar value but in a timezone the UTC offset is always the same as the offset right after the gap. -The value returned by ``dt.timestamp()`` given the invalid +The value returned by ``dt.timestamp()`` given a missing ``dt`` will be the larger of the two "nice to know" values if ``dt.first == True`` and the larger otherwise. @@ -179,10 +189,10 @@ Combining and splitting date and time ..................................... -The ``datetime.datetime.combine`` method will copy the value of the +The ``datetime.datetime.combine()`` method will copy the value of the ``first`` attribute to the resulting ``datetime.datetime`` instance. -The ``datetime.datetime.time`` method will copy the value of the +The ``datetime.datetime.time()`` method will copy the value of the ``first`` attribute to the resulting ``datetime.time`` instance. @@ -196,7 +206,7 @@ regardless of the value of ``first``. The basic implementation of ``fromutc()`` in the abstract -``datetime.tzinfo`` class, will not change. It is currently not +``datetime.tzinfo`` class will not change. It is currently not used anywhere in the stdlib because the only included ``tzinfo`` implementation (the ``datetime.timzeone`` class implementing fixed offset timezones) override ``fromutc()``. @@ -212,15 +222,16 @@ support variable UTC offsets (due to DST and other causes) must follow these guidelines. -New subclasses must override the base-class ``fromutc()`` method -and implement it so that in all cases where two UTC times ``u1`` -and ``u2`` (``u1`` <``u2``) correspond to the same local time +New subclasses must override the base-class ``fromutc()`` method and +implement it so that in all cases where two UTC times ``u1`` and +``u2`` (``u1`` <``u2``) correspond to the same local time ``fromutc(u1)`` will return an instance with ``first=True`` and -``fromutc(u2)`` will return an instance with ``first=False``. +``fromutc(u2)`` will return an instance with ``first=False``. In all +other cases the returned instance must have ``first=True``. New implementations of ``utcoffset()`` and ``dst()`` methods should ignore the value of ``first`` unless they are called on the ambiguous -or invalid times. +or missing times. On an ambiguous time introduced at the end of DST, the values returned by ``utcoffset()`` and ``dst()`` methods should be as follows @@ -236,7 +247,7 @@ where ``stdoff`` is the standard (non-DST) offset, ``hour = timedelta(hours=1)`` and ``zero = timedelta(0)``. -On an invalid time introduced at the start of DST, the values returned +On a missing time introduced at the start of DST, the values returned by ``utcoffset()`` and ``dst()`` methods should be as follows @@ -249,7 +260,7 @@ +-----------------+----------------+------------------+ -On ambiguous/invalid times introduced by the change in the standard time +On ambiguous/missing times introduced by the change in the standard time offset, the ``dst()`` method should return the same value regardless of the value of ``first`` and the ``utcoff()`` should return values according to the following table: @@ -259,7 +270,7 @@ +=================+================+=============================+ | ambiguous | oldoff | newoff = oldoff - delta | +-----------------+----------------+-----------------------------+ -| invalid | oldoff | newoff = oldoff + delta | +| missing | oldoff | newoff = oldoff + delta | +-----------------+----------------+-----------------------------+ -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 10 02:58:04 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 10 Aug 2015 00:58:04 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Updated_the_backwa?= =?utf-8?q?rd_compatibility_section=2E?= Message-ID: <20150810005804.94780.10500@psf.io> https://hg.python.org/peps/rev/73462ff8b394 changeset: 5949:73462ff8b394 user: Alexander Belopolsky date: Sun Aug 09 20:58:00 2015 -0400 summary: PEP 495: Updated the backward compatibility section. files: pep-0495.txt | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -318,8 +318,13 @@ Backward and Forward Compatibility ---------------------------------- -This proposal will have no effect on the programs that do not set the -``first`` flag explicitly or use tzinfo implementations that do. +This proposal will have little effect on the programs that do not read +the ``first`` flag explicitly or use tzinfo implementations that do. +The only visible change for such programs will be that conversions to +and from POSIX timestamps will now round-trip correctly (up to +floating point rounding). Programs that implemented work-arounds to +the old incorrect behavior will need to be modified. + Pickles produced by older programs will remain fully forward compatible. Only datetime/time instances with ``first=False`` pickled in the new versions will become unreadable by the older Python -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 10 05:25:16 2015 From: python-checkins at python.org (ned.deily) Date: Mon, 10 Aug 2015 03:25:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NzQ1?= =?utf-8?q?=3A_Prevent_IDLE_initialization_crash_with_Tk_8=2E4=3A?= Message-ID: <20150810032516.17725.53034@psf.io> https://hg.python.org/cpython/rev/e39c4373b83f changeset: 97350:e39c4373b83f branch: 3.5 parent: 97348:aa527ee0d27f user: Ned Deily date: Sun Aug 09 23:21:29 2015 -0400 summary: Issue #24745: Prevent IDLE initialization crash with Tk 8.4: "TkFixedFont" does not exist in 8.4. files: Lib/idlelib/configHandler.py | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -22,6 +22,7 @@ import sys from configparser import ConfigParser +from tkinter import TkVersion from tkinter.font import Font, nametofont class InvalidConfigType(Exception): pass @@ -688,13 +689,16 @@ bold = self.GetOption(configType, section, 'font-bold', default=0, type='bool') if (family == 'TkFixedFont'): - f = Font(name='TkFixedFont', exists=True, root=root) - actualFont = Font.actual(f) - family = actualFont['family'] - size = actualFont['size'] - if size < 0: - size = 10 # if font in pixels, ignore actual size - bold = actualFont['weight']=='bold' + if TkVersion < 8.5: + family = 'Courier' + else: + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' return (family, size, 'bold' if bold else 'normal') def LoadCfgFiles(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 10 05:25:21 2015 From: python-checkins at python.org (ned.deily) Date: Mon, 10 Aug 2015 03:25:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324745=3A_merge_from_3=2E5?= Message-ID: <20150810032521.111120.70708@psf.io> https://hg.python.org/cpython/rev/8c55fb5a11d8 changeset: 97351:8c55fb5a11d8 parent: 97349:f304ba9425a3 parent: 97350:e39c4373b83f user: Ned Deily date: Sun Aug 09 23:23:21 2015 -0400 summary: Issue #24745: merge from 3.5 files: Lib/idlelib/configHandler.py | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -22,6 +22,7 @@ import sys from configparser import ConfigParser +from tkinter import TkVersion from tkinter.font import Font, nametofont class InvalidConfigType(Exception): pass @@ -688,13 +689,16 @@ bold = self.GetOption(configType, section, 'font-bold', default=0, type='bool') if (family == 'TkFixedFont'): - f = Font(name='TkFixedFont', exists=True, root=root) - actualFont = Font.actual(f) - family = actualFont['family'] - size = actualFont['size'] - if size < 0: - size = 10 # if font in pixels, ignore actual size - bold = actualFont['weight']=='bold' + if TkVersion < 8.5: + family = 'Courier' + else: + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' return (family, size, 'bold' if bold else 'normal') def LoadCfgFiles(self): -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Mon Aug 10 10:23:08 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Mon, 10 Aug 2015 08:23:08 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-10 Message-ID: Results for project python_default-nightly, build date 2015-08-10 09:02:40 commit: 8c55fb5a11d8325b10a5494dd3c0d38098bbfaa5 revision date: 2015-08-10 06:23:21 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec 0.13387% -2.23466% :-( regex_v8 sec 0.34513% -3.33472% :-| nbody sec 1.01145% -0.48980% :-( json_dump_v2 sec 0.17926% -2.07488% :-| normal_startup sec 0.10821% 0.01852% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Mon Aug 10 15:17:37 2015 From: python-checkins at python.org (eric.smith) Date: Mon, 10 Aug 2015 13:17:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Small_typos=2E_Added_section_?= =?utf-8?q?about_nested_expressions_inside_format_specifiers=2E?= Message-ID: <20150810131736.110726.7263@psf.io> https://hg.python.org/peps/rev/32f2e29a125c changeset: 5950:32f2e29a125c user: Eric V. Smith date: Mon Aug 10 09:17:36 2015 -0400 summary: Small typos. Added section about nested expressions inside format specifiers. files: pep-0498.txt | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -229,7 +229,17 @@ Format specifiers ----------------- -Format specifiers are not interpreted by the f-string parser. Just as +Format specifiers may also contain evaluated expressions. This allows +code such as:: + + >>> width = 10 + >>> precision = 4 + >>> value = decimal.Decimal('12.34567') + >>> f'result: {value:{width}.{prevision}}' + 'result: 12.35' + +Once expressions in a format specifier are evaluated (if necessary), +format specifiers are not interpreted by the f-string evaluator. Just as in str.format(), they are merely passed in to the __format__() method of the object being formatted. @@ -325,7 +335,7 @@ Most of the discussions on python-ideas [#]_ focused on a few issues: - Whether to allow full Python expressions. - - How to designate f-strings, and how specify the locaton of + - How to designate f-strings, and how to specify the location of expressions in them. - How to concatenate adjacent strings and f-strings. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 10 19:16:00 2015 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Aug 2015 17:16:00 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_Martin=2E?= Message-ID: <20150810171559.29388.29817@psf.io> https://hg.python.org/devguide/rev/b10fd6c7d9ca changeset: 759:b10fd6c7d9ca user: Georg Brandl date: Mon Aug 10 19:15:56 2015 +0200 summary: Add Martin. files: developers.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -25,6 +25,9 @@ Permissions History ------------------- +- Martin Panter was given push privileges on August 10, 2015 by GFB, + on the recommendation of R. David Murray. + - Paul Moore was given push privileges on March 18, 2015 by Brett Cannon, on his own recommendation. -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Mon Aug 10 20:51:53 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 10 Aug 2015 18:51:53 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-494=3A_Add_recently_discu?= =?utf-8?q?ssed_PEPs_to_3=2E6_proposed_changes?= Message-ID: <20150810185153.94776.6464@psf.io> https://hg.python.org/peps/rev/bcb62c4edce8 changeset: 5951:bcb62c4edce8 user: Yury Selivanov date: Mon Aug 10 14:51:51 2015 -0400 summary: pep-494: Add recently discussed PEPs to 3.6 proposed changes files: pep-0494.txt | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/pep-0494.txt b/pep-0494.txt --- a/pep-0494.txt +++ b/pep-0494.txt @@ -49,7 +49,12 @@ Proposed changes for 3.6: -* TBD +* PEP 447, Add __getdescriptor__ method to metaclass +* PEP 498, Literal String Formatting +* PEP 499, python -m foo should bind sys.modules['foo'] in additon + to sys.modules['__main__'] +* PEP 501, Translation ready string interpolation + Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 11 02:18:06 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 00:18:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Touch-ups_for_Python_3=2E5_re?= =?utf-8?q?lease_schedule=2E?= Message-ID: <20150811001805.80812.23332@psf.io> https://hg.python.org/peps/rev/9534b23249f3 changeset: 5952:9534b23249f3 user: Larry Hastings date: Mon Aug 10 17:18:01 2015 -0700 summary: Touch-ups for Python 3.5 release schedule. files: pep-0478.txt | 47 +++++++++++++++------------------------ 1 files changed, 18 insertions(+), 29 deletions(-) diff --git a/pep-0478.txt b/pep-0478.txt --- a/pep-0478.txt +++ b/pep-0478.txt @@ -34,53 +34,42 @@ Release Schedule ================ -The releases: +The releases so far: - 3.5.0 alpha 1: February 8, 2015 - 3.5.0 alpha 2: March 9, 2015 - 3.5.0 alpha 3: March 29, 2015 - 3.5.0 alpha 4: April 19, 2015 - 3.5.0 beta 1: May 24, 2015 + (Beta 1 is also "feature freeze"--no new features beyond this point.) - 3.5.0 beta 2: May 31, 2015 - 3.5.0 beta 3: July 5, 2015 - 3.5.0 beta 4: July 26, 2015 -- 3.5.0 candidate 1: August 9, 2015 -- 3.5.0 candidate 2: August 23, 2015 -- 3.5.0 candidate 3: September 6, 2015 +- 3.5.0 release candidate 1: August 10, 2015 + +Planned future release dates: + +- 3.5.0 release candidate 2: August 23, 2015 +- 3.5.0 release candidate 3: September 6, 2015 - 3.5.0 final: September 13, 2015 -(Beta 1 is also "feature freeze"--no new features beyond this point.) - - Features for 3.5 ================ -Implemented / Final PEPs: - -* PEP 465, a new matrix multiplication operator -* PEP 461, %-formatting for binary strings -* PEP 471, os.scandir() -* PEP 479, change StopIteration handling inside generators * PEP 441, improved Python zip application support * PEP 448, additional unpacking generalizations -* PEP 486, make the Python Launcher aware of virtual environments -* PEP 475, retrying system calls that fail with EINTR +* PEP 461, "%-formatting" for bytes and bytearray objects +* PEP 465, a new operator ("@") for matrix multiplication +* PEP 471, os.scandir(), a fast new directory traversal function +* PEP 475, adding support for automatic retries of interrupted system calls +* PEP 479, change StopIteration handling inside generators +* PEP 484, the typing module, a new standard for type annotations +* PEP 485, math.isclose(), a function for testing approximate equality +* PEP 486, making the Widnows Python launcher aware of virtual environments +* PEP 488, eliminating .pyo files +* PEP 489, a new and improved mechanism for loading extension modules * PEP 492, coroutines with async and await syntax -* PEP 488, elimination of PYO files -* PEP 484, type hints -* PEP 489, redesigning extension module loading -* PEP 485, math.isclose(), a function for testing approximate equality - - -Proposed changes for 3.5: - -* PEP 431, improved support for time zone databases -* PEP 432, simplifying Python's startup sequence -* PEP 436, a build tool generating boilerplate for extension modules -* PEP 447, support for __locallookup__ metaclass method -* PEP 468, preserving the order of ``**kwargs`` in a function - Copyright -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 11 03:07:30 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 01:07:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Regenerated_py?= =?utf-8?q?doc_topics_for_Python_3=2E5=2E0rc1=2E?= Message-ID: <20150811010730.27304.5173@psf.io> https://hg.python.org/cpython/rev/562c4be02a5c changeset: 97352:562c4be02a5c branch: 3.5 parent: 97342:202a7aabd4fe user: Larry Hastings date: Sun Aug 09 03:34:21 2015 -0700 summary: Regenerated pydoc topics for Python 3.5.0rc1. files: Lib/pydoc_data/topics.py | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sat Jul 25 14:16:44 2015 +# Autogenerated by Sphinx on Sun Aug 9 03:32:48 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -19,18 +19,18 @@ 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nAn optional trailing comma may be present after the positional and\nkeyword arguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n', 'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. They\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and "{2,3}" are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of differing types depends on whether either of\nthe types provide explicit support for the comparison. Most numeric\ntypes can be compared with one another. When cross-type comparison is\nnot supported, the comparison method returns "NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', - 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= "async" funcdef\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', 'continue': u'\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', 'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works as follows:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string as a\nleft argument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', - 'customization': u'\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n', + 'customization': u'\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n By default, "__ne__()" delegates to "__eq__()" and inverts the\n result unless it is "NotImplemented". There are no other implied\n relationships among the comparison operators, for example, the\n truth of "(x.__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n', 'debugger': u'\n"pdb" --- The Python Debugger\n*****************************\n\n**Source code:** Lib/pdb.py\n\n======================================================================\n\nThe module "pdb" defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n"Pdb". This is currently undocumented but easily understood by reading\nthe source. The extension interface uses the modules "bdb" and "cmd".\n\nThe debugger\'s prompt is "(Pdb)". Typical usage to run a program under\ncontrol of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the "readline" module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the "p" command.\n\n"pdb.py" can also be invoked as a script to debug other scripts. For\nexample:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: "pdb.py" now accepts a "-c" option that executes\ncommands as if given in a ".pdbrc" file, see *Debugger Commands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the "continue" command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type "continue", or you can\n step through the statement using "step" or "next" (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module "__main__" is used. (See the\n explanation of the built-in "exec()" or "eval()" functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When "runeval()" returns, it returns the\n value of the expression. Otherwise this function is similar to\n "run()".\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When "runcall()" returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n "sys.last_traceback".\n\nThe "run*" functions and "set_trace()" are aliases for instantiating\nthe "Pdb" class and calling the method of the same name. If you want\nto access further features, you have to do this yourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n "Pdb" is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying "cmd.Cmd" class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses Ctrl-C on the console) when you give a\n "continue" command. This allows you to break into the debugger\n again by pressing Ctrl-C. If you want Pdb not to touch the SIGINT\n handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n"h(elp)" means that either "h" or "help" can be used to enter the help\ncommand (but not "he" or "hel", nor "H" or "Help" or "HELP").\nArguments to commands must be separated by whitespace (spaces or\ntabs). Optional arguments are enclosed in square brackets ("[]") in\nthe command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n("|").\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a "list" command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint ("!"). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by ";;".\n(A single ";" is not used as it is the separator for multiple commands\nin a line that is passed to the Python parser.) No intelligence is\napplied to separating the commands; the input is split at the first\n";;" pair, even if it is in the middle of a quoted string.\n\nIf a file ".pdbrc" exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ".pdbrc" can now contain commands that\ncontinue debugging, such as "continue" or "next". Previously, these\ncommands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. "help pdb"\n displays the full documentation (the docstring of the "pdb"\n module). Since the *command* argument must be an identifier, "help\n exec" must be entered to get help on the "!" command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on "sys.path". Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for "break".\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just "end" to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) p some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with "end"; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between "next" and "step"\n is that "step" stops inside a called function, while "next"\n executes called functions at (nearly) full speed, only stopping at\n the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a "for" loop or out\n of a "finally" clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With "." as argument, list 11 lines around the current line. With\n one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by "->". If an\n exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ">>", if it differs\n from the current line.\n\n New in version 3.2: The ">>" marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for "list".\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\n Note: "print()" can also be used, but is not a debugger command\n --- this executes the Python "print()" function.\n\npp expression\n\n Like the "p" command, except the value of the expression is pretty-\n printed using the "pprint" module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the "code" module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by "%1", "%2", and so on, while "%*" is replaced by all\n the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ".pdbrc" file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n "global" statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with "shlex" and the result is used as the new\n "sys.argv". History, breakpoints, actions and debugger options are\n preserved. "restart" is an alias for "run".\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module\n is determined by the "__name__" in the frame globals.\n', 'del': u'\nThe "del" statement\n*******************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a "global"\nstatement in the same code block. If the name is unbound, a\n"NameError" exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n', 'dict': u'\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n', - 'dynamic-features': u'\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'dynamic-features': u'\nInteraction with dynamic features\n*********************************\n\nName resolution of free variables occurs at runtime, not at compile\ntime. This means that the following code will print 42:\n\n i = 10\n def f():\n print(i)\n i = 42\n f()\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', 'else': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', 'exceptions': u'\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', - 'execmodel': u'\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\nas a command line argument to the interpreter) is a code block. A\nscript command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, an\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'execmodel': u'\nExecution model\n***************\n\n\nStructure of a programm\n=======================\n\nA Python program is constructed from code blocks. A *block* is a piece\nof Python program text that is executed as a unit. The following are\nblocks: a module, a function body, and a class definition. Each\ncommand typed interactively is a block. A script file (a file given\nas standard input to the interpreter or specified as a command line\nargument to the interpreter) is a code block. A script command (a\ncommand specified on the interpreter command line with the \'**-c**\'\noption) is a code block. The string argument passed to the built-in\nfunctions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\n\nNaming and binding\n==================\n\n\nBinding of names\n----------------\n\n*Names* refer to objects. Names are introduced by name binding\noperations.\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal" or "global". If a name is bound at the\nmodule level, it is a global variable. (The variables of the module\ncode block are local and global.) If a variable is used in a code\nblock but not defined there, it is a *free variable*.\n\nEach occurrence of a name in the program text refers to the *binding*\nof that name established by the following name resolution rules.\n\n\nResolution of names\n-------------------\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name.\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nWhen a name is not found at all, a "NameError" exception is raised. If\nthe current scope is a function scope, and the name refers to a local\nvariable that has not yet been bound to a value at the point where the\nname is used, an "UnboundLocalError" exception is raised.\n"UnboundLocalError" is a subclass of "NameError".\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nThe "nonlocal" statement causes corresponding names to refer to\npreviously bound variables in the nearest enclosing function scope.\n"SyntaxError" is raised at compile time if the given name does not\nexist in any enclosing function scope.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nClass definition blocks and arguments to "exec()" and "eval()" are\nspecial in the context of name resolution. A class definition is an\nexecutable statement that may use and define names. These references\nfollow the normal rules for name resolution with an exception that\nunbound local variables are looked up in the global namespace. The\nnamespace of the class definition becomes the attribute dictionary of\nthe class. The scope of names defined in a class block is limited to\nthe class block; it does not extend to the code blocks of methods --\nthis includes comprehensions and generator expressions since they are\nimplemented using a function scope. This means that the following\nwill fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\n\nBuiltins and restricted execution\n---------------------------------\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\n\nInteraction with dynamic features\n---------------------------------\n\nName resolution of free variables occurs at runtime, not at compile\ntime. This means that the following code will print 42:\n\n i = 10\n def f():\n print(i)\n i = 42\n f()\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', 'exprlists': u'\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n', 'floating': u'\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, "077e010" is legal, and denotes the same number\nas "77e10". The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator "-" and the\nliteral "1".\n', 'for': u'\nThe "for" statement\n*******************\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', @@ -46,7 +46,7 @@ 'integers': u'\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0xdeadbeef\n', 'lambda': u'\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) are used to create\nanonymous functions. The expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', 'lists': u'\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n', - 'naming': u'\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\nas a command line argument to the interpreter) is a code block. A\nscript command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, an\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'naming': u'\nNaming and binding\n******************\n\n\nBinding of names\n================\n\n*Names* refer to objects. Names are introduced by name binding\noperations.\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal" or "global". If a name is bound at the\nmodule level, it is a global variable. (The variables of the module\ncode block are local and global.) If a variable is used in a code\nblock but not defined there, it is a *free variable*.\n\nEach occurrence of a name in the program text refers to the *binding*\nof that name established by the following name resolution rules.\n\n\nResolution of names\n===================\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name.\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nWhen a name is not found at all, a "NameError" exception is raised. If\nthe current scope is a function scope, and the name refers to a local\nvariable that has not yet been bound to a value at the point where the\nname is used, an "UnboundLocalError" exception is raised.\n"UnboundLocalError" is a subclass of "NameError".\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nThe "nonlocal" statement causes corresponding names to refer to\npreviously bound variables in the nearest enclosing function scope.\n"SyntaxError" is raised at compile time if the given name does not\nexist in any enclosing function scope.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nClass definition blocks and arguments to "exec()" and "eval()" are\nspecial in the context of name resolution. A class definition is an\nexecutable statement that may use and define names. These references\nfollow the normal rules for name resolution with an exception that\nunbound local variables are looked up in the global namespace. The\nnamespace of the class definition becomes the attribute dictionary of\nthe class. The scope of names defined in a class block is limited to\nthe class block; it does not extend to the code blocks of methods --\nthis includes comprehensions and generator expressions since they are\nimplemented using a function scope. This means that the following\nwill fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\n\nBuiltins and restricted execution\n=================================\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\n\nInteraction with dynamic features\n=================================\n\nName resolution of free variables occurs at runtime, not at compile\ntime. This means that the following code will print 42:\n\n i = 10\n def f():\n print(i)\n i = 42\n f()\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', 'nonlocal': u'\nThe "nonlocal" statement\n************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe "nonlocal" statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope excluding\nglobals. This is important because the default behavior for binding is\nto search the local namespace first. The statement allows\nencapsulated code to rebind variables outside of the local scope\nbesides the global (module) scope.\n\nNames listed in a "nonlocal" statement, unlike those listed in a\n"global" statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a "nonlocal" statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also: **PEP 3104** - Access to Names in Outer Scopes\n\n The specification for the "nonlocal" statement.\n', 'numbers': u'\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n', 'numeric-types': u'\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n', @@ -60,8 +60,8 @@ 'shifting': u'\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by "pow(2,n)".\nA left shift by *n* bits is defined as multiplication with "pow(2,n)".\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n', 'slicings': u'\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary is indexed\n(using the same "__getitem__()" method as normal subscription) with a\nkey that is constructed from the slice list, as follows. If the slice\nlist contains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of a proper slice is a\nslice object (see section *The standard type hierarchy*) whose\n"start", "stop" and "step" attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting "None" for missing expressions.\n', 'specialattrs': u'\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n', - 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n', - 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n The outermost leading and trailing *chars* argument values are\n stripped from the string. Characters are removed from the leading\n end until reaching a string character that is not contained in the\n set of characters in *chars*. A similar action takes place on the\n trailing end. For example:\n\n >>> comment_string = \'#....... Section 3.2.1 Issue #32 .......\'\n >>> comment_string.strip(\'.#! \')\n \'Section 3.2.1 Issue #32\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n', + 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n By default, "__ne__()" delegates to "__eq__()" and inverts the\n result unless it is "NotImplemented". There are no other implied\n relationships among the comparison operators, for example, the\n truth of "(x.__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n', + 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n The outermost leading and trailing *chars* argument values are\n stripped from the string. Characters are removed from the leading\n end until reaching a string character that is not contained in the\n set of characters in *chars*. A similar action takes place on the\n trailing end. For example:\n\n >>> comment_string = \'#....... Section 3.2.1 Issue #32 .......\'\n >>> comment_string.strip(\'.#! \')\n \'Section 3.2.1 Issue #32\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(table)\n\n Return a copy of the string in which each character has been mapped\n through the given translation table. The table must be an object\n that implements indexing via "__getitem__()", typically a *mapping*\n or *sequence*. When indexed by a Unicode ordinal (an integer), the\n table object can do any of the following: return a Unicode ordinal\n or a string, to map the character to one or more other characters;\n return "None", to delete the character from the return string; or\n raise a "LookupError" exception, to map the character to itself.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n See also the "codecs" module for a more flexible approach to custom\n character mappings.\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n', 'strings': u'\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix string literals with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\nNew in version 3.3: The "\'rb\'" prefix of raw bytes literals has been\nadded as a synonym of "\'br\'".\n\nNew in version 3.3: Support for the unicode legacy literal\n("u\'value\'") was reintroduced to simplify the maintenance of dual\nPython 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted literals, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the literal. (A "quote" is the character used to open the\nliteral, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in string\nand bytes literals are interpreted according to rules similar to those\nused by Standard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the result*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw literal, quotes can be escaped with a backslash, but the\nbackslash remains in the result; for example, "r"\\""" is a valid\nstring literal consisting of two characters: a backslash and a double\nquote; "r"\\"" is not a valid string literal (even a raw string cannot\nend in an odd number of backslashes). Specifically, *a raw literal\ncannot end in a single backslash* (since the backslash would escape\nthe following quote character). Note also that a single backslash\nfollowed by a newline is interpreted as those two characters as part\nof the literal, *not* as a line continuation.\n', 'subscriptions': u'\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription\n(lists or dictionaries for example). User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', 'truth': u'\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 03:07:32 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 01:07:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Release_bump_f?= =?utf-8?q?or_Python_3=2E5=2E0rc1=2E?= Message-ID: <20150811010730.10876.81729@psf.io> https://hg.python.org/cpython/rev/01a684180b19 changeset: 97353:01a684180b19 branch: 3.5 user: Larry Hastings date: Sun Aug 09 03:41:04 2015 -0700 summary: Release bump for Python 3.5.0rc1. files: Include/patchlevel.h | 6 +++--- README | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 4 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.5.0b4+" +#define PY_VERSION "3.5.0rc1" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.5.0 beta 4 -=================================== +This is Python version 3.5.0 release candidate 1 +================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 03:07:32 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 01:07:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_tag_v3?= =?utf-8?q?=2E5=2E0rc1_for_changeset_01a684180b19?= Message-ID: <20150811010730.68119.72899@psf.io> https://hg.python.org/cpython/rev/de2eefb43019 changeset: 97354:de2eefb43019 branch: 3.5 user: Larry Hastings date: Sun Aug 09 03:41:22 2015 -0700 summary: Added tag v3.5.0rc1 for changeset 01a684180b19 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -152,3 +152,4 @@ 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 +01a684180b19a32a8e85566d43f3b62966ad0a30 v3.5.0rc1 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 03:07:35 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 01:07:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merged_fixes_for_two_bad_bugs=2E__This_will_be_the_new_Python_?= =?utf-8?b?My41LjByYzEu?= Message-ID: <20150811010735.7969.12047@psf.io> https://hg.python.org/cpython/rev/1a58b1227501 changeset: 97355:1a58b1227501 branch: 3.5 tag: v3.5.0rc1 parent: 97354:de2eefb43019 parent: 97350:e39c4373b83f user: Larry Hastings date: Sun Aug 09 21:37:20 2015 -0700 summary: Merged fixes for two bad bugs. This will be the new Python 3.5.0rc1. files: .hgtags | 1 - Lib/idlelib/configHandler.py | 18 +++++++---- Lib/test/test_asyncio/test_subprocess.py | 6 +++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -152,4 +152,3 @@ 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 -01a684180b19a32a8e85566d43f3b62966ad0a30 v3.5.0rc1 diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -22,6 +22,7 @@ import sys from configparser import ConfigParser +from tkinter import TkVersion from tkinter.font import Font, nametofont class InvalidConfigType(Exception): pass @@ -688,13 +689,16 @@ bold = self.GetOption(configType, section, 'font-bold', default=0, type='bool') if (family == 'TkFixedFont'): - f = Font(name='TkFixedFont', exists=True, root=root) - actualFont = Font.actual(f) - family = actualFont['family'] - size = actualFont['size'] - if size < 0: - size = 10 # if font in pixels, ignore actual size - bold = actualFont['weight']=='bold' + if TkVersion < 8.5: + family = 'Courier' + else: + f = Font(name='TkFixedFont', exists=True, root=root) + actualFont = Font.actual(f) + family = actualFont['family'] + size = actualFont['size'] + if size < 0: + size = 10 # if font in pixels, ignore actual size + bold = actualFont['weight']=='bold' return (family, size, 'bold' if bold else 'normal') def LoadCfgFiles(self): diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -417,7 +417,11 @@ def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - with mock.patch('subprocess.Popen') as popen: + if sys.platform == 'win32': + target = 'asyncio.windows_utils.Popen' + else: + target = 'subprocess.Popen' + with mock.patch(target) as popen: exc = ZeroDivisionError popen.side_effect = exc -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 03:07:35 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 01:07:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_tag_v3?= =?utf-8?q?=2E5=2E0rc1_for_changeset_1a58b1227501?= Message-ID: <20150811010735.27808.88189@psf.io> https://hg.python.org/cpython/rev/399362d0e504 changeset: 97356:399362d0e504 branch: 3.5 user: Larry Hastings date: Sun Aug 09 21:37:24 2015 -0700 summary: Added tag v3.5.0rc1 for changeset 1a58b1227501 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -152,3 +152,4 @@ 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 +1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 03:07:36 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Aug 2015 01:07:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Post-release_b?= =?utf-8?q?ump_for_Python_3=2E5=2E0rc1=2E?= Message-ID: <20150811010735.81152.38315@psf.io> https://hg.python.org/cpython/rev/c11694040866 changeset: 97357:c11694040866 branch: 3.5 user: Larry Hastings date: Mon Aug 10 18:03:52 2015 -0700 summary: Post-release bump for Python 3.5.0rc1. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.5.0rc1" +#define PY_VERSION "3.5.0rc1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 release candidate 2? +=============================================== + +Release date: 2015-08-23 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 release candidate 1? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 06:03:52 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 11 Aug 2015 04:03:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E5?= Message-ID: <20150811040352.10874.42451@psf.io> https://hg.python.org/cpython/rev/a411062ba778 changeset: 97359:a411062ba778 parent: 97351:8c55fb5a11d8 parent: 97358:7cfe20a6395d user: Steve Dower date: Mon Aug 10 21:01:00 2015 -0700 summary: Merge from 3.5 files: .hgtags | 1 + Lib/platform.py | 2 +- 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -152,3 +152,4 @@ 7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 +1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -440,7 +440,7 @@ # Try some common cmd strings for cmd in ('ver', 'command /c ver', 'cmd /c ver'): try: - pipe = popen(cmd) + pipe = os.popen(cmd) info = pipe.read() if pipe.close(): raise OSError('command failed') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 11 06:03:52 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 11 Aug 2015 04:03:52 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODM5?= =?utf-8?q?=3A_platform=2E=5Fsyscmd=5Fver_raises_DeprecationWarning?= Message-ID: <20150811040352.114216.72069@psf.io> https://hg.python.org/cpython/rev/7cfe20a6395d changeset: 97358:7cfe20a6395d branch: 3.5 user: Steve Dower date: Mon Aug 10 20:57:37 2015 -0700 summary: Issue #24839: platform._syscmd_ver raises DeprecationWarning files: Lib/platform.py | 2 +- Misc/NEWS | 1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -440,7 +440,7 @@ # Try some common cmd strings for cmd in ('ver', 'command /c ver', 'cmd /c ver'): try: - pipe = popen(cmd) + pipe = os.popen(cmd) info = pipe.read() if pipe.close(): raise OSError('command failed') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,7 @@ Library ------- +- Issue #24839: platform._syscmd_ver raises DeprecationWarning What's New in Python 3.5.0 release candidate 1? =============================================== -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Tue Aug 11 10:51:52 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Tue, 11 Aug 2015 08:51:52 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-11 Message-ID: Results for project python_default-nightly, build date 2015-08-11 09:02:11 commit: a411062ba7789bb192778f8d26f83e4227f0d1eb revision date: 2015-08-11 07:01:00 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-| pybench sec 0.26438% -1.96437% :-( regex_v8 sec -0.43251% -3.78165% :-( nbody sec -3.33148% -3.83759% :-( json_dump_v2 sec -1.26208% -3.36314% :-| normal_startup sec -0.14068% -0.12213% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Tue Aug 11 15:32:02 2015 From: python-checkins at python.org (eric.smith) Date: Tue, 11 Aug 2015 13:32:02 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Moved_the_deprecation_stateme?= =?utf-8?q?nt_to_a_place_that_makes_more_sense=2E_Thanks_Mike?= Message-ID: <20150811133155.10900.72015@psf.io> https://hg.python.org/peps/rev/c9fdc3498a67 changeset: 5953:c9fdc3498a67 user: Eric V. Smith date: Tue Aug 11 09:32:15 2015 -0400 summary: Moved the deprecation statement to a place that makes more sense. Thanks Mike Miller. files: pep-0498.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -22,6 +22,9 @@ "f-strings", taken from the leading character used to denote such strings. +This PEP does not propose to remove or deprecate any of the existing +string formatting mechanisms. + f-strings provide a way to combine string literals with Python expressions, using a minimal syntax. It should be noted that an f-string is really an expression evaluated at run time, not a constant @@ -38,9 +41,6 @@ >>> f'He said his name is {name!r}.' "He said his name is 'Fred'." -This PEP does not propose to remove or deprecate any of the existing -string formatting mechanisms. - A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to support a subset of Python expressions, and did not support the type-specific string formatting (the __format__ method) which was -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 11 22:00:17 2015 From: python-checkins at python.org (robert.collins) Date: Tue, 11 Aug 2015 20:00:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=239232=3A_Support_t?= =?utf-8?q?railing_commas_in_function_declarations=2E?= Message-ID: <20150811200016.7975.75079@psf.io> https://hg.python.org/cpython/rev/419ceb531bab changeset: 97360:419ceb531bab user: Robert Collins date: Wed Aug 12 08:00:06 2015 +1200 summary: Issue #9232: Support trailing commas in function declarations. For example, "def f(*, a = 3,): pass" is now legal. Patch from Mark Dickinson. files: Doc/reference/compound_stmts.rst | 8 +- Grammar/Grammar | 17 +- Lib/test/test_grammar.py | 38 +++++ Misc/NEWS | 4 + Python/ast.c | 23 ++- Python/graminit.c | 122 ++++++++++-------- 6 files changed, 139 insertions(+), 73 deletions(-) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -471,10 +471,10 @@ decorators: `decorator`+ decorator: "@" `dotted_name` ["(" [`parameter_list` [","]] ")"] NEWLINE dotted_name: `identifier` ("." `identifier`)* - parameter_list: (`defparameter` ",")* - : | "*" [`parameter`] ("," `defparameter`)* ["," "**" `parameter`] - : | "**" `parameter` - : | `defparameter` [","] ) + parameter_list: `defparameter` ("," `defparameter`)* ["," [`parameter_list_starargs`]] + : | `parameter_list_starargs` + parameter_list_starargs: "*" [`parameter`] ("," `defparameter`)* ["," ["**" `parameter` [","]]] + : | "**" `parameter` [","] parameter: `identifier` [":" `expression`] defparameter: `parameter` ["=" `expression`] funcname: `identifier` diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -27,13 +27,18 @@ funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' -typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' - ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]] - | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef) +typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [ + '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] + | '**' tfpdef [',']]] + | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] + | '**' tfpdef [',']) tfpdef: NAME [':' test] -varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' - ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] - | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) +varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ + '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [',']]] + | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [','] +) vfpdef: NAME stmt: simple_stmt | compound_stmt diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -295,6 +295,10 @@ pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200) pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100) + self.assertRaises(SyntaxError, eval, "def f(*): pass") + self.assertRaises(SyntaxError, eval, "def f(*,): pass") + self.assertRaises(SyntaxError, eval, "def f(*, **kwds): pass") + # keyword arguments after *arglist def f(*args, **kwargs): return args, kwargs @@ -352,6 +356,23 @@ check_syntax_error(self, "f(*g(1=2))") check_syntax_error(self, "f(**g(1=2))") + # Check trailing commas are permitted in funcdef argument list + def f(a,): pass + def f(*args,): pass + def f(**kwds,): pass + def f(a, *args,): pass + def f(a, **kwds,): pass + def f(*args, b,): pass + def f(*, b,): pass + def f(*args, **kwds,): pass + def f(a, *args, b,): pass + def f(a, *, b,): pass + def f(a, *args, **kwds,): pass + def f(*args, b, **kwds,): pass + def f(*, b, **kwds,): pass + def f(a, *args, b, **kwds,): pass + def f(a, *, b, **kwds,): pass + def test_lambdef(self): ### lambdef: 'lambda' [varargslist] ':' test l1 = lambda : 0 @@ -370,6 +391,23 @@ self.assertEqual(l6(1,2), 1+2+20) self.assertEqual(l6(1,2,k=10), 1+2+10) + # check that trailing commas are permitted + l10 = lambda a,: 0 + l11 = lambda *args,: 0 + l12 = lambda **kwds,: 0 + l13 = lambda a, *args,: 0 + l14 = lambda a, **kwds,: 0 + l15 = lambda *args, b,: 0 + l16 = lambda *, b,: 0 + l17 = lambda *args, **kwds,: 0 + l18 = lambda a, *args, b,: 0 + l19 = lambda a, *, b,: 0 + l20 = lambda a, *args, **kwds,: 0 + l21 = lambda *args, b, **kwds,: 0 + l22 = lambda *, b, **kwds,: 0 + l23 = lambda a, *args, b, **kwds,: 0 + l24 = lambda a, *, b, **kwds,: 0 + ### stmt: simple_stmt | compound_stmt # Tested below diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #9232: Modify Python's grammar to allow trailing commas in the + argument list of a function declaration. For example, "def f(*, a = + 3,): pass" is now legal. Patch from Mark Dickinson. + - Issue #24667: Resize odict in all cases that the underlying dict resizes. Library diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -1260,16 +1260,20 @@ and varargslist (lambda definition). parameters: '(' [typedargslist] ')' - typedargslist: ((tfpdef ['=' test] ',')* - ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] - | '**' tfpdef) - | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) + typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [ + '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] + | '**' tfpdef [',']]] + | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] + | '**' tfpdef [',']) tfpdef: NAME [':' test] - varargslist: ((vfpdef ['=' test] ',')* - ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] - | '**' vfpdef) - | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) + varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ + '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [',']]] + | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [','] + ) vfpdef: NAME + */ int i, j, k, nposargs = 0, nkwonlyargs = 0; int nposdefaults = 0, found_default = 0; @@ -1371,7 +1375,8 @@ i += 2; /* the name and the comma */ break; case STAR: - if (i+1 >= NCH(n)) { + if (i+1 >= NCH(n) || + (i+2 == NCH(n) && TYPE(CHILD(n, i+1)) == COMMA)) { ast_error(c, CHILD(n, i), "named arguments must follow bare *"); return NULL; diff --git a/Python/graminit.c b/Python/graminit.c --- a/Python/graminit.c +++ b/Python/graminit.c @@ -204,11 +204,13 @@ {32, 7}, {0, 6}, }; -static arc arcs_9_7[2] = { +static arc arcs_9_7[3] = { {30, 12}, {34, 3}, -}; -static arc arcs_9_8[1] = { + {0, 7}, +}; +static arc arcs_9_8[2] = { + {32, 13}, {0, 8}, }; static arc arcs_9_9[2] = { @@ -221,35 +223,39 @@ {0, 10}, }; static arc arcs_9_11[3] = { - {30, 13}, - {32, 14}, + {30, 14}, + {32, 15}, {0, 11}, }; static arc arcs_9_12[3] = { {32, 7}, - {31, 15}, + {31, 16}, {0, 12}, }; -static arc arcs_9_13[2] = { - {32, 14}, +static arc arcs_9_13[1] = { {0, 13}, }; static arc arcs_9_14[2] = { - {30, 16}, + {32, 15}, + {0, 14}, +}; +static arc arcs_9_15[3] = { + {30, 17}, {34, 3}, -}; -static arc arcs_9_15[1] = { + {0, 15}, +}; +static arc arcs_9_16[1] = { {26, 6}, }; -static arc arcs_9_16[3] = { - {32, 14}, - {31, 17}, - {0, 16}, -}; -static arc arcs_9_17[1] = { - {26, 13}, -}; -static state states_9[18] = { +static arc arcs_9_17[3] = { + {32, 15}, + {31, 18}, + {0, 17}, +}; +static arc arcs_9_18[1] = { + {26, 14}, +}; +static state states_9[19] = { {3, arcs_9_0}, {3, arcs_9_1}, {3, arcs_9_2}, @@ -257,17 +263,18 @@ {1, arcs_9_4}, {4, arcs_9_5}, {2, arcs_9_6}, - {2, arcs_9_7}, - {1, arcs_9_8}, + {3, arcs_9_7}, + {2, arcs_9_8}, {2, arcs_9_9}, {3, arcs_9_10}, {3, arcs_9_11}, {3, arcs_9_12}, - {2, arcs_9_13}, + {1, arcs_9_13}, {2, arcs_9_14}, - {1, arcs_9_15}, - {3, arcs_9_16}, - {1, arcs_9_17}, + {3, arcs_9_15}, + {1, arcs_9_16}, + {3, arcs_9_17}, + {1, arcs_9_18}, }; static arc arcs_10_0[1] = { {23, 1}, @@ -319,11 +326,13 @@ {32, 7}, {0, 6}, }; -static arc arcs_11_7[2] = { +static arc arcs_11_7[3] = { {36, 12}, {34, 3}, -}; -static arc arcs_11_8[1] = { + {0, 7}, +}; +static arc arcs_11_8[2] = { + {32, 13}, {0, 8}, }; static arc arcs_11_9[2] = { @@ -336,35 +345,39 @@ {0, 10}, }; static arc arcs_11_11[3] = { - {36, 13}, - {32, 14}, + {36, 14}, + {32, 15}, {0, 11}, }; static arc arcs_11_12[3] = { {32, 7}, - {31, 15}, + {31, 16}, {0, 12}, }; -static arc arcs_11_13[2] = { - {32, 14}, +static arc arcs_11_13[1] = { {0, 13}, }; static arc arcs_11_14[2] = { - {36, 16}, + {32, 15}, + {0, 14}, +}; +static arc arcs_11_15[3] = { + {36, 17}, {34, 3}, -}; -static arc arcs_11_15[1] = { + {0, 15}, +}; +static arc arcs_11_16[1] = { {26, 6}, }; -static arc arcs_11_16[3] = { - {32, 14}, - {31, 17}, - {0, 16}, -}; -static arc arcs_11_17[1] = { - {26, 13}, -}; -static state states_11[18] = { +static arc arcs_11_17[3] = { + {32, 15}, + {31, 18}, + {0, 17}, +}; +static arc arcs_11_18[1] = { + {26, 14}, +}; +static state states_11[19] = { {3, arcs_11_0}, {3, arcs_11_1}, {3, arcs_11_2}, @@ -372,17 +385,18 @@ {1, arcs_11_4}, {4, arcs_11_5}, {2, arcs_11_6}, - {2, arcs_11_7}, - {1, arcs_11_8}, + {3, arcs_11_7}, + {2, arcs_11_8}, {2, arcs_11_9}, {3, arcs_11_10}, {3, arcs_11_11}, {3, arcs_11_12}, - {2, arcs_11_13}, + {1, arcs_11_13}, {2, arcs_11_14}, - {1, arcs_11_15}, - {3, arcs_11_16}, - {1, arcs_11_17}, + {3, arcs_11_15}, + {1, arcs_11_16}, + {3, arcs_11_17}, + {1, arcs_11_18}, }; static arc arcs_12_0[1] = { {23, 1}, @@ -1879,11 +1893,11 @@ "\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {264, "parameters", 0, 4, states_8, "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {265, "typedargslist", 0, 18, states_9, + {265, "typedargslist", 0, 19, states_9, "\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {266, "tfpdef", 0, 4, states_10, "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {267, "varargslist", 0, 18, states_11, + {267, "varargslist", 0, 19, states_11, "\000\000\200\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {268, "vfpdef", 0, 2, states_12, "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 12 03:53:41 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 12 Aug 2015 01:53:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODQ3?= =?utf-8?q?=3A_Fixes_tcltk_installer_layout_of_VC_runtime_DLL?= Message-ID: <20150812015340.68127.3812@psf.io> https://hg.python.org/cpython/rev/3cb97ffd9ddf changeset: 97361:3cb97ffd9ddf branch: 3.5 parent: 97358:7cfe20a6395d user: Steve Dower date: Tue Aug 11 18:49:13 2015 -0700 summary: Issue #24847: Fixes tcltk installer layout of VC runtime DLL files: Misc/NEWS | 2 ++ Tools/msi/tcltk/tcltk.wixproj | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #24847: Fixes tcltk installer layout of VC runtime DLL + - Issue #24839: platform._syscmd_ver raises DeprecationWarning What's New in Python 3.5.0 release candidate 1? diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -28,9 +28,9 @@ tcltk_dlls - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ + $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ + $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ + $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ DLLs\ tcltk_dlls -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 12 03:53:41 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 12 Aug 2015 01:53:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324847=3A_Fixes_tcltk_installer_layout_of_VC_run?= =?utf-8?q?time_DLL?= Message-ID: <20150812015340.114220.48133@psf.io> https://hg.python.org/cpython/rev/13ceedb92923 changeset: 97362:13ceedb92923 parent: 97360:419ceb531bab parent: 97361:3cb97ffd9ddf user: Steve Dower date: Tue Aug 11 18:51:00 2015 -0700 summary: Issue #24847: Fixes tcltk installer layout of VC runtime DLL files: Tools/msi/tcltk/tcltk.wixproj | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -28,9 +28,9 @@ tcltk_dlls - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ + $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ + $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ + $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ DLLs\ tcltk_dlls -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Wed Aug 12 10:04:53 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Wed, 12 Aug 2015 08:04:53 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-12 Message-ID: Results for project python_default-nightly, build date 2015-08-12 09:02:44 commit: 13ceedb9292343bf33f88069184cc7b50b9827e3 revision date: 2015-08-12 04:51:00 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec -0.19788% -2.16613% :-( regex_v8 sec 0.29353% -3.47703% :-( nbody sec 1.13430% -2.65976% :-| json_dump_v2 sec 1.42464% -1.89059% :-| normal_startup sec -0.30499% -0.42749% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Thu Aug 13 01:10:56 2015 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Aug 2015 23:10:56 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_a_chapter_about_runni?= =?utf-8?q?ng_buildslaves=2E?= Message-ID: <20150812231054.80954.76313@psf.io> https://hg.python.org/devguide/rev/7368a61d28de changeset: 760:7368a61d28de user: R David Murray date: Wed Aug 12 19:10:48 2015 -0400 summary: Add a chapter about running buildslaves. This is an expanded and updated version of the information that used to live in the wiki. The mac stuff is based on a recent mac setup I did, and so should be accurate and (as of the commit :) up to date. files: buildbots.rst | 3 + buildslave.rst | 285 +++++++++++++++++++++++++++++++++++++ index.rst | 1 + 3 files changed, 289 insertions(+), 0 deletions(-) diff --git a/buildbots.rst b/buildbots.rst --- a/buildbots.rst +++ b/buildbots.rst @@ -223,3 +223,6 @@ .. note:: For security reasons, it is impossible to build repositories from outside the http://hg.python.org realm. + +.. seealso:: + :ref:`buildslave` diff --git a/buildslave.rst b/buildslave.rst new file mode 100644 --- /dev/null +++ b/buildslave.rst @@ -0,0 +1,285 @@ + +.. _buildslave: + +Running a buildslave +==================== + +Python's :ref:`buildbots` system was discussed earlier. We sometimes refer to +the collection of *build slaves* as our "buildbot fleet". The machines that +comprise the fleet are voluntarily contributed resources. Many are run by +individual volunteers out of their own pockets and time, while others are +supported by corporations. Even the corporate sponsored buildbots, however, +tend to exist because some individual championed them, made them a reality, and +is committed to maintaining them. + +Anyone can contribute a buildbot to the fleet. This chapter describes how +to go about setting up a buildslave, getting it added, and some hints about +buildbot maintenance. + +Anyone running a buildbot that is part of the fleet should subscribe to the +`python-buildbots `_ +mailing list. This mailing list is also the place to contact if you want to +contribute a buildbot but have questions. + +As for what kind of buildbot to run...take a look at our `current fleet +`_. Pretty much anything that isn't +on that list would be interesting: different Linux/unix distributions, +different versions of the various OSes, other OSes if you or someone are +prepared to make the test suite actually pass on that new OS. Even if you only +want to run an OS that's already on our list there may be utility in setting it +up: we also need to build and test python under various alternate build +configurations. Post to the mailing list and talk about what you'd like to +contribute. + + +Preparing for buildslave setup +------------------------------ + +Since the goal is to build Python from source, the system will need to have +everything required to do normal python development: a compiler, a linker, and +(except on windows) the "development" headers for any of the optional modules +(zlib, OpenSSL, etc) supported by the platform. Follow the steps outlined in +:ref:`setup` for the target platform, all the way through to having a working +compiled python. + +In order to set up the buildbot software, you will need to obtain an identifier +and password for your buildslave so it can join the fleet. Email +python-buildbots at python.org to discuss adding your buildslave and to obtain the +needed slavename and password. You can do some of the steps that follow +before having the credentials, but it is easiest to have them before +the "buildslave" step below. + + +Setting up the buildslave +------------------------- + +You need a recent version of the `buildbot `_ software, +and you will probably want a separate 'buildbot' user to run the buildbot +software. You may also want to set the buildbot up using a virtual +environment, depending on you manage your system. We won't cover how to that +here; it doesn't differ from setting up a virtual environment for any other +software, but you'll need to modify the sequence of steps below as appropriate +if you choose that path. + +For Linux: + + * If your package manager provides the buildbot slave software, that is + probably the best way to install it; it may create the buildbot user for + you, in which case you can skip that step. Otherwise, do ``pip install + buildbot-slave``. + * Create a ``buildbot`` user (using, eg: ``useradd``) if necessary. + * Log in as the buildbot user. + +For Mac: + + * Create a buildbot user using the OS/X control panel user admin. It + should be a "standard" user. + * Log in as the buildbot user. + * Install either the Python 2.7 bundle from python.org [#]_, or pip. + * Open a terminal window. + * Execute ``pip install buildbot-slave``. + +For Windows: + + * TBD + +In a terminal window for the buildbot user, issue the following commands (you +can put the ``buildarea`` wherever you want to):: + + mkdir buildarea + buildslave create-slave buildarea buildbot.python.org:9020 slavename slavepasswd + +Once this initial slave setup completes, you should edit the files +``buildarea/info/admin`` and ``buildarea/info/host`` to provide your contact +info and information on the host configuration, respectively. This information +will be presented in the buildbot web pages that display information about the +builders running on your buildslave. + +You will also want to make sure that the buildslave is started when the +machine reboots: + +For Linux: + + * Add the following line to ``/etc/crontab``:: + + @reboot buildslave restart /path/to/buildarea + + Note that we use ``restart`` rather than ``start`` in case a crash has + left a ``twistd.pid`` file behind. + +For OSX: + + * Create a bin directory for your buildbot user:: + + mkdir bin + + * Place the following script, named ``run_slave.sh``, into that directory:: + + #!/bin/bash + export PATH=/usr/local/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:$PATH + export LC_CTYPE=en_US.utf-8 + cd /Users/buildbot/buildarea + twistd --nodaemon --python=buildbot.tac --logfile=buildbot.log --prefix=slave + + If you use pip with Apple's system python, add '/System' to the front of + the path to the Python bin directory. + + * Place a file with the following contents into ``/Library/LaunchDaemons``:: + + + + + + Label + net.buildbot.slave + UserName + buildbot + WorkingDirectory + /Users/buildbot/buildarea + ProgramArguments + + /Users/buildbot/bin/run_slave.sh + + StandardOutPath + twistd.log + StandardErrorPath + twistd.log + KeepAlive + + SessionCreate + + + + + The recommended name for the file is ``net.buildbot.slave``. + +For Windows: + + * TBD + +To start the buildslave running for your initial testing, you can do:: + + buildslave start ~/buildarea + +Then you can either wait for someone to make a commit, or you can pick a +builder associated with your buildslave from the `list of builders +`_ and force a build. + +In any case you should initially monitor builds on your builders to make sure +the tests are passing and to resolve any platform issues that may be revealed +by tests that fail. Unfortunately we do not currently have a way to notify you +only of failures on your builders, so doing periodic spot checks is also a good +idea. + + +Buildslave operation +-------------------- + +Most of the time, running a buildslave is a "set and forget" operation, +depending on the level of involvement you want to have in resolving bugs +revealed by your builders. There are, however, times when it is helpful or +even necessary for you to get involved. As noted above, you should be +subscribed to ``python-buildbots at python.org`` so that you will be made +aware of any fleet-wide issues. + +Necessary tasks include, obviously, keeping the buildbot running. Currently +the system for notifying buildbot owners when their slaves go offline is not +working; this is something we hope to resolve. So currently it is helpful if +you periodically check the status of your buildslave. We will also contact you +via your contact address in ``buildarea/info/admin`` when we notice there is a +problem that has not been resolved for some period of time and you have +not responded to a posting on the python-buildbots list about it. + +We currently do not have a minimum version requirement for the buildslave +software. However, this is something we will probably establish as we tune the +fleet, so another task will be to occasionally upgrade the buildslave software. +Coordination for this will be done via ``python-buildbots at python.org``. + +The most interesting extra involvement is when your buildslave reveals a unique +or almost-unique problem: a test that is failing on your system but not on +other systems. In this case you should be prepared to offer debugging help to +the people working on the bug: running tests by hand on the buildslave machine +or, if possible, providing ssh access to a committer to run experiments to try +to resolve the issue. + + +Required Ports +-------------- + +The buildslave operates as a *client* to the *buildmaster*. This means that +all network connections are *outbound*. This is true also for the network +tests in the test suite. Most consumer firewalls will allow any outbound +traffic, so normally you do not need to worry about what ports the buildbot +uses. However, corporate firewalls are sometimes more restrictive, so here is +a table listing all of the outbound ports used by the buildbot and the python +test suite (this list may not be complete as new tests may have been added +since this table was last vetted): + +======= =================== ================================================ +Port Host Description +======= =================== ================================================ +20, 21 ftp.debian.org test_urllib2net +53 your DNS server test_socket, and others implicitly +80 python.org (several tests) + example.com +119 news.gmane.org test_nntplib +443 (various) test_ssl +465 smtp.gmail.com test_smtpnet +587 smtp.gmail.com test_smtpnet +9020 python.org connection to buildmaster +======= =================== ================================================ + +Many tests will also create local TCP sockets and connect to them, usually +using either ``localhost`` or ``127.0.0.1``. + + +Required Resources +------------------ + +Based on the last time we did a `survey +`_ on +buildbot requirements, the recommended resource allocations for a python +buildbot are at least: + + * 2 CPUs + * 512 MB RAM + * 30 GB free disk space + +The bigmem tests won't run in this configuration, since they require +substantially more memory, but these resources should be sufficient to ensure +that Python compiles correctly on the platform and can run the rest of the test +suite. + + +Security Considerations +----------------------- + +We only allow builds to be triggered against commits to the CPython repository, +or committer-initiated branches hosted on hg.python.org. This means that the +code your buildbot will run will have been vetted by a committer. However, +mistakes and bugs happen, as could a compromise, so keep this in mind when +siting your buildbot on your network and establishing the security around it. +Treat the buildbot like you would any resource that is public facing and might +get hacked (use a VM and/or jail/chroot/solaris zone, put it in a DMZ, etc). +While the buildbot does not have any ports open for inbound traffic (and is not +public facing in that sense), committer mistakes do happen, and security flaws +are discovered in both released and unreleased code, so treating the buildbot +as if it were fully public facing is a good policy. + +Code runs differently as privileged and unprivileged users. We would love to +have builders running as privileged accounts, but security considerations do +make that difficult, as access to root can provide access to surprising +resources (such as spoofed IP packets, changes in MAC addresses, etc) even on a +VM setup. But if you are confident in your setup, we'd love to have a buildbot +that runs python as root. + +Note that the above is a summary of a `discussion +`_ on +python-dev about buildbot security that includes examples of the tests for +which privilege matters. There was no final consensus, but the information is +useful as a point of reference. + +.. [#] If the buildbot is going to do Framework builds, it is better to + use the Apple-shipped Python so as to avoid any chance of the buildbot + picking up components from the installed python.org python. diff --git a/index.rst b/index.rst --- a/index.rst +++ b/index.rst @@ -218,6 +218,7 @@ compiler coverity clang + buildslave gitdevs faq -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Thu Aug 13 01:38:54 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 12 Aug 2015 23:38:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzNzI1?= =?utf-8?q?=3A_Overhaul_tempfile_docs=2E?= Message-ID: <20150812233854.27312.14714@psf.io> https://hg.python.org/cpython/rev/51d00482d403 changeset: 97363:51d00482d403 branch: 3.5 parent: 97361:3cb97ffd9ddf user: Robert Collins date: Thu Aug 13 11:38:02 2015 +1200 summary: Issue #23725: Overhaul tempfile docs. Patch from Zbigniew J?drzejewski-Szmek. files: Doc/library/tempfile.rst | 153 +++++++++++++++----------- Misc/NEWS | 6 + 2 files changed, 94 insertions(+), 65 deletions(-) diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -16,16 +16,18 @@ -------------- -This module generates temporary files and directories. It works on all -supported platforms. It provides three new functions, -:func:`NamedTemporaryFile`, :func:`mkstemp`, and :func:`mkdtemp`, which should -eliminate all remaining need to use the insecure :func:`mktemp` function. -Temporary file names created by this module no longer contain the process ID; -instead a string of six random characters is used. +This module creates temporary files and directories. It works on all +supported platforms. :class:`TemporaryFile`, :class:`NamedTemporaryFile`, +:class:`TemporaryDirectory`, and :class:`SpooledTemporaryFile` are high-level +interfaces which provide automatic cleanup and can be used as +context managers. :func:`mkstemp` and +:func:`mkdtemp` are lower-level functions which require manual cleanup. -Also, all the user-callable functions now take additional arguments which -allow direct control over the location and name of temporary files. It is -no longer necessary to use the global *tempdir* variable. +All the user-callable functions and constructors take additional arguments which +allow direct control over the location and name of temporary files and +directories. Files names used by this module include a string of +random characters which allows those files to be securely created in +shared temporary directories. To maintain backward compatibility, the argument order is somewhat odd; it is recommended to use keyword arguments for clarity. @@ -34,28 +36,33 @@ .. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None) Return a :term:`file-like object` that can be used as a temporary storage area. - The file is created using :func:`mkstemp`. It will be destroyed as soon + The file is created securely, using the same rules as :func:`mkstemp`. It will be destroyed as soon as it is closed (including an implicit close when the object is garbage - collected). Under Unix, the directory entry for the file is removed + collected). Under Unix, the directory entry for the file is either not created at all or is removed immediately after the file is created. Other platforms do not support this; your code should not rely on a temporary file created using this function having or not having a visible name in the file system. + The resulting object can be used as a context manager (see + :ref:`tempfile-examples`). On completion of the context or + destruction of the file object the temporary file will be removed + from the filesystem. + The *mode* parameter defaults to ``'w+b'`` so that the file created can be read and written without being closed. Binary mode is used so that it behaves consistently on all platforms without regard for the data that is stored. *buffering*, *encoding* and *newline* are interpreted as for :func:`open`. - The *dir*, *prefix* and *suffix* parameters are passed to :func:`mkstemp`. + The *dir*, *prefix* and *suffix* parameters have the same meaning + as with :func:`mkstemp`. The returned object is a true file object on POSIX platforms. On other platforms, it is a file-like object whose :attr:`!file` attribute is the - underlying true file object. This file-like object can be used in a - :keyword:`with` statement, just like a normal file. + underlying true file object. The :py:data:`os.O_TMPFILE` flag is used if it is available and works - (Linux-specific, require Linux kernel 3.11 or later). + (Linux-specific, requires Linux kernel 3.11 or later). .. versionchanged:: 3.5 @@ -101,10 +108,9 @@ .. function:: TemporaryDirectory(suffix='', prefix='tmp', dir=None) - This function creates a temporary directory using :func:`mkdtemp` - (the supplied arguments are passed directly to the underlying function). + This function securely creates a temporary directory using the same rules as :func:`mkdtemp`. The resulting object can be used as a context manager (see - :ref:`context-managers`). On completion of the context or destruction + :ref:`tempfile-examples`). On completion of the context or destruction of the temporary directory object the newly created temporary directory and all its contents are removed from the filesystem. @@ -194,49 +200,14 @@ an appropriate default value to be used. -.. function:: mktemp(suffix='', prefix='tmp', dir=None) +.. function:: gettempdir() - .. deprecated:: 2.3 - Use :func:`mkstemp` instead. + Return the name of the directory used for temporary files. This + defines the default value for the *dir* argument to all functions + in this module. - Return an absolute pathname of a file that did not exist at the time the - call is made. The *prefix*, *suffix*, and *dir* arguments are the same - as for :func:`mkstemp`. - - .. warning:: - - Use of this function may introduce a security hole in your program. By - the time you get around to doing anything with the file name it returns, - someone else may have beaten you to the punch. :func:`mktemp` usage can - be replaced easily with :func:`NamedTemporaryFile`, passing it the - ``delete=False`` parameter:: - - >>> f = NamedTemporaryFile(delete=False) - >>> f.name - '/tmp/tmptjujjt' - >>> f.write(b"Hello World!\n") - 13 - >>> f.close() - >>> os.unlink(f.name) - >>> os.path.exists(f.name) - False - -The module uses a global variable that tell it how to construct a -temporary name. They are initialized at the first call to any of the -functions above. The caller may change them, but this is discouraged; use -the appropriate function arguments, instead. - - -.. data:: tempdir - - When set to a value other than ``None``, this variable defines the - default value for the *dir* argument to all the functions defined in this - module. - - If ``tempdir`` is unset or ``None`` at any call to any of the above - functions, Python searches a standard list of directories and sets - *tempdir* to the first one which the calling user can create files in. - The list is: + Python searches a standard list of directories to find one which + the calling user can create files in. The list is: #. The directory named by the :envvar:`TMPDIR` environment variable. @@ -254,12 +225,8 @@ #. As a last resort, the current working directory. - -.. function:: gettempdir() - - Return the directory currently selected to create temporary files in. If - :data:`tempdir` is not ``None``, this simply returns its contents; otherwise, - the search described above is performed, and the result returned. + The result of this search is cached, see the description of + :data:`tempdir` below. .. function:: gettempdirb() @@ -278,6 +245,23 @@ .. versionadded:: 3.5 +The module uses a global variable to store the name of the directory +used for temporary files returned by :func:`gettempdir`. It can be +set directly to override the selection process, but this is discouraged. +All functions in this module take a *dir* argument which can be used +to specify the directory and this is the recommend approach. + +.. data:: tempdir + + When set to a value other than ``None``, this variable defines the + default value for the *dir* argument to all the functions defined in this + module. + + If ``tempdir`` is unset or ``None`` at any call to any of the above + functions except :func:`gettempprefix` it is initalized following the + algorithm described in :func:`gettempdir`. + +.. _tempfile-examples: Examples -------- @@ -311,3 +295,42 @@ >>> # directory and contents have been removed + +Deprecated functions and variables +---------------------------------- + +A historical way to create temporary files was to first generate a +file name with the :func:`mktemp` function and then create a file +using this name. Unfortunately this is not secure, because a different +process may create a file with this name in the time between the call +to :func:`mktemp` and the subsequent attempt to create the file by the +first process. The solution is to combine the two steps and create the +file immediately. This approach is used by :func:`mkstemp` and the +other functions described above. + +.. function:: mktemp(suffix='', prefix='tmp', dir=None) + + .. deprecated:: 2.3 + Use :func:`mkstemp` instead. + + Return an absolute pathname of a file that did not exist at the time the + call is made. The *prefix*, *suffix*, and *dir* arguments are the same + as for :func:`mkstemp`. + + .. warning:: + + Use of this function may introduce a security hole in your program. By + the time you get around to doing anything with the file name it returns, + someone else may have beaten you to the punch. :func:`mktemp` usage can + be replaced easily with :func:`NamedTemporaryFile`, passing it the + ``delete=False`` parameter:: + + >>> f = NamedTemporaryFile(delete=False) + >>> f.name + '/tmp/tmptjujjt' + >>> f.write(b"Hello World!\n") + 13 + >>> f.close() + >>> os.unlink(f.name) + >>> os.path.exists(f.name) + False diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,12 @@ - Issue #24839: platform._syscmd_ver raises DeprecationWarning +Documentation +------------- + +- Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. + Patch from Zbigniew J?drzejewski-Szmek. + What's New in Python 3.5.0 release candidate 1? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 01:38:56 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 12 Aug 2015 23:38:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323725=3A_Overhaul_tempfile_docs=2E?= Message-ID: <20150812233854.53430.7071@psf.io> https://hg.python.org/cpython/rev/256d2f01e975 changeset: 97364:256d2f01e975 parent: 97362:13ceedb92923 parent: 97363:51d00482d403 user: Robert Collins date: Thu Aug 13 11:38:44 2015 +1200 summary: Issue #23725: Overhaul tempfile docs. Patch from Zbigniew J?drzejewski-Szmek. files: Doc/library/tempfile.rst | 153 +++++++++++++++----------- Misc/NEWS | 3 + 2 files changed, 91 insertions(+), 65 deletions(-) diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -16,16 +16,18 @@ -------------- -This module generates temporary files and directories. It works on all -supported platforms. It provides three new functions, -:func:`NamedTemporaryFile`, :func:`mkstemp`, and :func:`mkdtemp`, which should -eliminate all remaining need to use the insecure :func:`mktemp` function. -Temporary file names created by this module no longer contain the process ID; -instead a string of six random characters is used. +This module creates temporary files and directories. It works on all +supported platforms. :class:`TemporaryFile`, :class:`NamedTemporaryFile`, +:class:`TemporaryDirectory`, and :class:`SpooledTemporaryFile` are high-level +interfaces which provide automatic cleanup and can be used as +context managers. :func:`mkstemp` and +:func:`mkdtemp` are lower-level functions which require manual cleanup. -Also, all the user-callable functions now take additional arguments which -allow direct control over the location and name of temporary files. It is -no longer necessary to use the global *tempdir* variable. +All the user-callable functions and constructors take additional arguments which +allow direct control over the location and name of temporary files and +directories. Files names used by this module include a string of +random characters which allows those files to be securely created in +shared temporary directories. To maintain backward compatibility, the argument order is somewhat odd; it is recommended to use keyword arguments for clarity. @@ -34,28 +36,33 @@ .. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None) Return a :term:`file-like object` that can be used as a temporary storage area. - The file is created using :func:`mkstemp`. It will be destroyed as soon + The file is created securely, using the same rules as :func:`mkstemp`. It will be destroyed as soon as it is closed (including an implicit close when the object is garbage - collected). Under Unix, the directory entry for the file is removed + collected). Under Unix, the directory entry for the file is either not created at all or is removed immediately after the file is created. Other platforms do not support this; your code should not rely on a temporary file created using this function having or not having a visible name in the file system. + The resulting object can be used as a context manager (see + :ref:`tempfile-examples`). On completion of the context or + destruction of the file object the temporary file will be removed + from the filesystem. + The *mode* parameter defaults to ``'w+b'`` so that the file created can be read and written without being closed. Binary mode is used so that it behaves consistently on all platforms without regard for the data that is stored. *buffering*, *encoding* and *newline* are interpreted as for :func:`open`. - The *dir*, *prefix* and *suffix* parameters are passed to :func:`mkstemp`. + The *dir*, *prefix* and *suffix* parameters have the same meaning + as with :func:`mkstemp`. The returned object is a true file object on POSIX platforms. On other platforms, it is a file-like object whose :attr:`!file` attribute is the - underlying true file object. This file-like object can be used in a - :keyword:`with` statement, just like a normal file. + underlying true file object. The :py:data:`os.O_TMPFILE` flag is used if it is available and works - (Linux-specific, require Linux kernel 3.11 or later). + (Linux-specific, requires Linux kernel 3.11 or later). .. versionchanged:: 3.5 @@ -101,10 +108,9 @@ .. function:: TemporaryDirectory(suffix='', prefix='tmp', dir=None) - This function creates a temporary directory using :func:`mkdtemp` - (the supplied arguments are passed directly to the underlying function). + This function securely creates a temporary directory using the same rules as :func:`mkdtemp`. The resulting object can be used as a context manager (see - :ref:`context-managers`). On completion of the context or destruction + :ref:`tempfile-examples`). On completion of the context or destruction of the temporary directory object the newly created temporary directory and all its contents are removed from the filesystem. @@ -194,49 +200,14 @@ an appropriate default value to be used. -.. function:: mktemp(suffix='', prefix='tmp', dir=None) +.. function:: gettempdir() - .. deprecated:: 2.3 - Use :func:`mkstemp` instead. + Return the name of the directory used for temporary files. This + defines the default value for the *dir* argument to all functions + in this module. - Return an absolute pathname of a file that did not exist at the time the - call is made. The *prefix*, *suffix*, and *dir* arguments are the same - as for :func:`mkstemp`. - - .. warning:: - - Use of this function may introduce a security hole in your program. By - the time you get around to doing anything with the file name it returns, - someone else may have beaten you to the punch. :func:`mktemp` usage can - be replaced easily with :func:`NamedTemporaryFile`, passing it the - ``delete=False`` parameter:: - - >>> f = NamedTemporaryFile(delete=False) - >>> f.name - '/tmp/tmptjujjt' - >>> f.write(b"Hello World!\n") - 13 - >>> f.close() - >>> os.unlink(f.name) - >>> os.path.exists(f.name) - False - -The module uses a global variable that tell it how to construct a -temporary name. They are initialized at the first call to any of the -functions above. The caller may change them, but this is discouraged; use -the appropriate function arguments, instead. - - -.. data:: tempdir - - When set to a value other than ``None``, this variable defines the - default value for the *dir* argument to all the functions defined in this - module. - - If ``tempdir`` is unset or ``None`` at any call to any of the above - functions, Python searches a standard list of directories and sets - *tempdir* to the first one which the calling user can create files in. - The list is: + Python searches a standard list of directories to find one which + the calling user can create files in. The list is: #. The directory named by the :envvar:`TMPDIR` environment variable. @@ -254,12 +225,8 @@ #. As a last resort, the current working directory. - -.. function:: gettempdir() - - Return the directory currently selected to create temporary files in. If - :data:`tempdir` is not ``None``, this simply returns its contents; otherwise, - the search described above is performed, and the result returned. + The result of this search is cached, see the description of + :data:`tempdir` below. .. function:: gettempdirb() @@ -278,6 +245,23 @@ .. versionadded:: 3.5 +The module uses a global variable to store the name of the directory +used for temporary files returned by :func:`gettempdir`. It can be +set directly to override the selection process, but this is discouraged. +All functions in this module take a *dir* argument which can be used +to specify the directory and this is the recommend approach. + +.. data:: tempdir + + When set to a value other than ``None``, this variable defines the + default value for the *dir* argument to all the functions defined in this + module. + + If ``tempdir`` is unset or ``None`` at any call to any of the above + functions except :func:`gettempprefix` it is initalized following the + algorithm described in :func:`gettempdir`. + +.. _tempfile-examples: Examples -------- @@ -311,3 +295,42 @@ >>> # directory and contents have been removed + +Deprecated functions and variables +---------------------------------- + +A historical way to create temporary files was to first generate a +file name with the :func:`mktemp` function and then create a file +using this name. Unfortunately this is not secure, because a different +process may create a file with this name in the time between the call +to :func:`mktemp` and the subsequent attempt to create the file by the +first process. The solution is to combine the two steps and create the +file immediately. This approach is used by :func:`mkstemp` and the +other functions described above. + +.. function:: mktemp(suffix='', prefix='tmp', dir=None) + + .. deprecated:: 2.3 + Use :func:`mkstemp` instead. + + Return an absolute pathname of a file that did not exist at the time the + call is made. The *prefix*, *suffix*, and *dir* arguments are the same + as for :func:`mkstemp`. + + .. warning:: + + Use of this function may introduce a security hole in your program. By + the time you get around to doing anything with the file name it returns, + someone else may have beaten you to the punch. :func:`mktemp` usage can + be replaced easily with :func:`NamedTemporaryFile`, passing it the + ``delete=False`` parameter:: + + >>> f = NamedTemporaryFile(delete=False) + >>> f.name + '/tmp/tmptjujjt' + >>> f.write(b"Hello World!\n") + 13 + >>> f.close() + >>> os.unlink(f.name) + >>> os.path.exists(f.name) + False diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -84,6 +84,9 @@ Documentation ------------- +- Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. + Patch from Zbigniew J?drzejewski-Szmek. + - Issue #24129: Clarify the reference documentation for name resolution. This includes removing the assumption that readers will be familiar with the name resolution scheme Python used prior to the introduction of lexical -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Thu Aug 13 11:09:46 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Thu, 13 Aug 2015 09:09:46 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-13 Message-ID: Results for project python_default-nightly, build date 2015-08-13 09:02:23 commit: 256d2f01e97536ce4b3d9d5e32feba910f2fe285 revision date: 2015-08-13 02:38:44 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec 0.15277% -2.01005% :-( regex_v8 sec -4.45294% -8.08479% :-( nbody sec 0.60969% -2.03385% :-( json_dump_v2 sec -1.86425% -3.79008% :-| normal_startup sec 0.42337% -0.00232% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Thu Aug 13 16:09:47 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 13 Aug 2015 14:09:47 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIxMTY3OiBGaXgg?= =?utf-8?q?definition_of_NAN_when_ICC_used_without_-fp-model_strict=2E?= Message-ID: <20150813140947.27797.63317@psf.io> https://hg.python.org/cpython/rev/d9c85b6bab3a changeset: 97365:d9c85b6bab3a branch: 2.7 parent: 97340:089f1a23dfac user: R David Murray date: Thu Aug 13 09:48:35 2015 -0400 summary: #21167: Fix definition of NAN when ICC used without -fp-model strict. Patch from Chris Hogan of Intel, reviewed by Mark Dickinson. files: Include/pymath.h | 24 +++++++++++++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -152,7 +152,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -573,6 +573,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + - Issue #24467: Fixed possible buffer over-read in bytearray. The bytearray object now always allocates place for trailing null byte and it's buffer now is always null-terminated. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 16:09:49 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 13 Aug 2015 14:09:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIxMTY3OiBGaXgg?= =?utf-8?q?definition_of_NAN_when_ICC_used_without_-fp-model_strict=2E?= Message-ID: <20150813140947.27800.40545@psf.io> https://hg.python.org/cpython/rev/5e71a489f01d changeset: 97366:5e71a489f01d branch: 3.4 parent: 97347:2648dddd3248 user: R David Murray date: Thu Aug 13 09:58:07 2015 -0400 summary: #21167: Fix definition of NAN when ICC used without -fp-model strict. Patch from Chris Hogan of Intel, reviewed by Mark Dickinson. files: Include/pymath.h | 24 +++++++++++++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -150,7 +150,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -583,6 +583,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + - Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 16:09:54 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 13 Aug 2015 14:09:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge=3A_=2321167=3A_Fix_definition_of_NAN_when_ICC_used_witho?= =?utf-8?q?ut_-fp-model_strict=2E?= Message-ID: <20150813140948.53436.21133@psf.io> https://hg.python.org/cpython/rev/e3008318f76b changeset: 97367:e3008318f76b branch: 3.5 parent: 97363:51d00482d403 parent: 97366:5e71a489f01d user: R David Murray date: Thu Aug 13 10:04:21 2015 -0400 summary: Merge: #21167: Fix definition of NAN when ICC used without -fp-model strict. files: Include/pymath.h | 24 +++++++++++++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -150,7 +150,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -594,6 +594,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 16:09:54 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 13 Aug 2015 14:09:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2321167=3A_Fix_definition_of_NAN_when_ICC_used?= =?utf-8?q?_without_-fp-model_strict=2E?= Message-ID: <20150813140948.81048.48511@psf.io> https://hg.python.org/cpython/rev/1dd4f473c627 changeset: 97368:1dd4f473c627 parent: 97364:256d2f01e975 parent: 97367:e3008318f76b user: R David Murray date: Thu Aug 13 10:07:54 2015 -0400 summary: Merge: #21167: Fix definition of NAN when ICC used without -fp-model strict. files: Include/pymath.h | 24 +++++++++++++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -150,7 +150,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -594,6 +594,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + - Issue #9232: Modify Python's grammar to allow trailing commas in the argument list of a function declaration. For example, "def f(*, a = 3,): pass" is now legal. Patch from Mark Dickinson. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 20:37:54 2015 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 13 Aug 2015 18:37:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2316554=3A_fix_description_for_MAKE=5FCLOSURE=2E__Initi?= =?utf-8?q?al_patch_by_Daniel_Urban=2E?= Message-ID: <20150813183754.27284.48663@psf.io> https://hg.python.org/cpython/rev/2a41fb63c095 changeset: 97370:2a41fb63c095 branch: 3.5 parent: 97367:e3008318f76b parent: 97369:c515b40a70eb user: Antoine Pitrou date: Thu Aug 13 20:37:28 2015 +0200 summary: Issue #16554: fix description for MAKE_CLOSURE. Initial patch by Daniel Urban. files: Doc/library/dis.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -946,8 +946,8 @@ Creates a new function object, sets its *__closure__* slot, and pushes it on the stack. TOS is the :term:`qualified name` of the function, TOS1 is the code associated with the function, and TOS2 is the tuple containing cells for - the closure's free variables. The function also has *argc* default - parameters, which are found below the cells. + the closure's free variables. *argc* is interpreted as in ``MAKE_FUNCTION``; + the annotations and defaults are also in the same order below TOS2. .. opcode:: BUILD_SLICE (argc) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 20:37:56 2015 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 13 Aug 2015 18:37:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316554=3A_fix_description_for_MAKE=5FCLOSURE=2E_?= =?utf-8?q?_Initial_patch_by_Daniel_Urban=2E?= Message-ID: <20150813183754.53426.11365@psf.io> https://hg.python.org/cpython/rev/7aed2d7e7dd5 changeset: 97371:7aed2d7e7dd5 parent: 97368:1dd4f473c627 parent: 97370:2a41fb63c095 user: Antoine Pitrou date: Thu Aug 13 20:37:40 2015 +0200 summary: Issue #16554: fix description for MAKE_CLOSURE. Initial patch by Daniel Urban. files: Doc/library/dis.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -946,8 +946,8 @@ Creates a new function object, sets its *__closure__* slot, and pushes it on the stack. TOS is the :term:`qualified name` of the function, TOS1 is the code associated with the function, and TOS2 is the tuple containing cells for - the closure's free variables. The function also has *argc* default - parameters, which are found below the cells. + the closure's free variables. *argc* is interpreted as in ``MAKE_FUNCTION``; + the annotations and defaults are also in the same order below TOS2. .. opcode:: BUILD_SLICE (argc) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 20:37:56 2015 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 13 Aug 2015 18:37:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE2NTU0?= =?utf-8?q?=3A_fix_description_for_MAKE=5FCLOSURE=2E__Initial_patch_by_Dan?= =?utf-8?q?iel_Urban=2E?= Message-ID: <20150813183754.53418.11784@psf.io> https://hg.python.org/cpython/rev/c515b40a70eb changeset: 97369:c515b40a70eb branch: 3.4 parent: 97366:5e71a489f01d user: Antoine Pitrou date: Thu Aug 13 20:37:08 2015 +0200 summary: Issue #16554: fix description for MAKE_CLOSURE. Initial patch by Daniel Urban. files: Doc/library/dis.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -887,8 +887,8 @@ Creates a new function object, sets its *__closure__* slot, and pushes it on the stack. TOS is the :term:`qualified name` of the function, TOS1 is the code associated with the function, and TOS2 is the tuple containing cells for - the closure's free variables. The function also has *argc* default - parameters, which are found below the cells. + the closure's free variables. *argc* is interpreted as in ``MAKE_FUNCTION``; + the annotations and defaults are also in the same order below TOS2. .. opcode:: BUILD_SLICE (argc) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 13 21:37:28 2015 From: python-checkins at python.org (charles-francois.natali) Date: Thu, 13 Aug 2015 19:37:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323530=3A_fix_clin?= =?utf-8?q?ic_comment=2E?= Message-ID: <20150813193728.27788.63440@psf.io> https://hg.python.org/cpython/rev/23c6cc5d5b8f changeset: 97372:23c6cc5d5b8f user: Charles-Fran?ois Natali date: Thu Aug 13 20:37:08 2015 +0100 summary: Issue #23530: fix clinic comment. files: Modules/clinic/posixmodule.c.h | 10 +++++++--- Modules/posixmodule.c | 12 +++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -2116,7 +2116,7 @@ "sched_getaffinity($module, pid, /)\n" "--\n" "\n" -"Return the affinity of the process identified by pid.\n" +"Return the affinity of the process identified by pid (or the current process if zero).\n" "\n" "The affinity is returned as a set of CPU identifiers."); @@ -5178,7 +5178,11 @@ "cpu_count($module, /)\n" "--\n" "\n" -"Return the number of CPUs in the system; return None if indeterminable."); +"Return the number of CPUs in the system; return None if indeterminable.\n" +"\n" +"This number is not equivalent to the number of CPUs the current process can\n" +"use. The number of usable CPUs can be obtained with\n" +"``len(os.sched_getaffinity(0))``"); #define OS_CPU_COUNT_METHODDEF \ {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, @@ -5788,4 +5792,4 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=f3f92b2d2e2c3fe3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=35b50461dbecd65d input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5767,7 +5767,7 @@ static PyObject * os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=b431a8f310e369e7 input=eaf161936874b8a1]*/ +/*[clinic end generated code: output=b431a8f310e369e7 input=983ce7cb4a565980]*/ { int cpu, ncpus, count; size_t setsize; @@ -11201,14 +11201,16 @@ /*[clinic input] os.cpu_count -Return the number of CPUs in the system; return None if indeterminable. This -number is not equivalent to the number of CPUs the current process can use. -The number of usable CPUs can be obtained with ``len(os.sched_getaffinity(0))`` +Return the number of CPUs in the system; return None if indeterminable. + +This number is not equivalent to the number of CPUs the current process can +use. The number of usable CPUs can be obtained with +``len(os.sched_getaffinity(0))`` [clinic start generated code]*/ static PyObject * os_cpu_count_impl(PyModuleDef *module) -/*[clinic end generated code: output=c59ee7f6bce832b8 input=d55e2f8f3823a628]*/ +/*[clinic end generated code: output=c59ee7f6bce832b8 input=e7c8f4ba6dbbadd3]*/ { int ncpu = 0; #ifdef MS_WINDOWS -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 01:50:35 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 13 Aug 2015 23:50:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2321159=3A_Improve_message_in_configparser=2EInterpolat?= =?utf-8?q?ionMissingOptionError=2E?= Message-ID: <20150813235035.31707.33361@psf.io> https://hg.python.org/cpython/rev/1a144ff2d78b changeset: 97374:1a144ff2d78b branch: 3.5 parent: 97370:2a41fb63c095 parent: 97373:267422f7c927 user: Robert Collins date: Fri Aug 14 11:47:41 2015 +1200 summary: Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. files: Lib/configparser.py | 29 +++++++++++----------- Lib/test/test_configparser.py | 7 +++-- Misc/NEWS | 3 ++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Lib/configparser.py b/Lib/configparser.py --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -263,12 +263,9 @@ """A string substitution required a setting which was not available.""" def __init__(self, option, section, rawval, reference): - msg = ("Bad value substitution:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\tkey : %s\n" - "\trawval : %s\n" - % (section, option, reference, rawval)) + msg = ("Bad value substitution: option {!r} in section {!r} contains " + "an interpolation key {!r} which is not a valid option name. " + "Raw value: {!r}".format(option, section, reference, rawval)) InterpolationError.__init__(self, option, section, msg) self.reference = reference self.args = (option, section, rawval, reference) @@ -286,11 +283,11 @@ """Raised when substitutions are nested too deeply.""" def __init__(self, option, section, rawval): - msg = ("Value interpolation too deeply recursive:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\trawval : %s\n" - % (section, option, rawval)) + msg = ("Recursion limit exceeded in value substitution: option {!r} " + "in section {!r} contains an interpolation key which " + "cannot be substituted in {} steps. Raw value: {!r}" + "".format(option, section, MAX_INTERPOLATION_DEPTH, + rawval)) InterpolationError.__init__(self, option, section, msg) self.args = (option, section, rawval) @@ -406,8 +403,9 @@ def _interpolate_some(self, parser, option, accum, rest, section, map, depth): + rawval = parser.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) + raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("%") if p < 0: @@ -432,7 +430,7 @@ v = map[var] except KeyError: raise InterpolationMissingOptionError( - option, section, rest, var) from None + option, section, rawval, var) from None if "%" in v: self._interpolate_some(parser, option, accum, v, section, map, depth + 1) @@ -466,8 +464,9 @@ def _interpolate_some(self, parser, option, accum, rest, section, map, depth): + rawval = parser.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) + raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("$") if p < 0: @@ -504,7 +503,7 @@ "More than one ':' found: %r" % (rest,)) except (KeyError, NoSectionError, NoOptionError): raise InterpolationMissingOptionError( - option, section, rest, ":".join(path)) from None + option, section, rawval, ":".join(path)) from None if "$" in v: self._interpolate_some(parser, opt, accum, v, sect, dict(parser.items(sect, raw=True)), diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -847,7 +847,8 @@ "something with lots of interpolation (10 steps)") e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11") if self.interpolation == configparser._UNSET: - self.assertEqual(e.args, ("bar11", "Foo", "%(with1)s")) + self.assertEqual(e.args, ("bar11", "Foo", + "something %(with11)s lots of interpolation (11 steps)")) elif isinstance(self.interpolation, configparser.LegacyInterpolation): self.assertEqual(e.args, ("bar11", "Foo", "something %(with11)s lots of interpolation (11 steps)")) @@ -861,7 +862,7 @@ self.assertEqual(e.option, "name") if self.interpolation == configparser._UNSET: self.assertEqual(e.args, ('name', 'Interpolation Error', - '', 'reference')) + '%(reference)s', 'reference')) elif isinstance(self.interpolation, configparser.LegacyInterpolation): self.assertEqual(e.args, ('name', 'Interpolation Error', '%(reference)s', 'reference')) @@ -1177,7 +1178,7 @@ with self.assertRaises(exception_class) as cm: cf['interpolated']['$trying'] self.assertEqual(cm.exception.reference, 'dollars:${sick') - self.assertEqual(cm.exception.args[2], '}') #rawval + self.assertEqual(cm.exception.args[2], '${dollars:${sick}}') #rawval def test_case_sensitivity_basic(self): ini = textwrap.dedent(""" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,9 @@ Library ------- +- Issue #21159: Improve message in configparser.InterpolationMissingOptionError. + Patch from ?ukasz Langa. + - Issue #24847: Fixes tcltk installer layout of VC runtime DLL - Issue #24839: platform._syscmd_ver raises DeprecationWarning -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 01:50:35 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 13 Aug 2015 23:50:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxMTU5?= =?utf-8?q?=3A_Improve_message_in_configparser=2EInterpolationMissingOptio?= =?utf-8?q?nError=2E?= Message-ID: <20150813235035.53414.4007@psf.io> https://hg.python.org/cpython/rev/267422f7c927 changeset: 97373:267422f7c927 branch: 3.4 parent: 97369:c515b40a70eb user: Robert Collins date: Fri Aug 14 11:11:35 2015 +1200 summary: Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. files: Lib/configparser.py | 29 +++++++++++----------- Lib/test/test_configparser.py | 7 +++-- Misc/NEWS | 3 ++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Lib/configparser.py b/Lib/configparser.py --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -241,12 +241,9 @@ """A string substitution required a setting which was not available.""" def __init__(self, option, section, rawval, reference): - msg = ("Bad value substitution:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\tkey : %s\n" - "\trawval : %s\n" - % (section, option, reference, rawval)) + msg = ("Bad value substitution: option {!r} in section {!r} contains " + "an interpolation key {!r} which is not a valid option name. " + "Raw value: {!r}".format(option, section, reference, rawval)) InterpolationError.__init__(self, option, section, msg) self.reference = reference self.args = (option, section, rawval, reference) @@ -264,11 +261,11 @@ """Raised when substitutions are nested too deeply.""" def __init__(self, option, section, rawval): - msg = ("Value interpolation too deeply recursive:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\trawval : %s\n" - % (section, option, rawval)) + msg = ("Recursion limit exceeded in value substitution: option {!r} " + "in section {!r} contains an interpolation key which " + "cannot be substituted in {} steps. Raw value: {!r}" + "".format(option, section, MAX_INTERPOLATION_DEPTH, + rawval)) InterpolationError.__init__(self, option, section, msg) self.args = (option, section, rawval) @@ -384,8 +381,9 @@ def _interpolate_some(self, parser, option, accum, rest, section, map, depth): + rawval = parser.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) + raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("%") if p < 0: @@ -410,7 +408,7 @@ v = map[var] except KeyError: raise InterpolationMissingOptionError( - option, section, rest, var) + option, section, rawval, var) if "%" in v: self._interpolate_some(parser, option, accum, v, section, map, depth + 1) @@ -444,8 +442,9 @@ def _interpolate_some(self, parser, option, accum, rest, section, map, depth): + rawval = parser.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) + raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("$") if p < 0: @@ -482,7 +481,7 @@ "More than one ':' found: %r" % (rest,)) except (KeyError, NoSectionError, NoOptionError): raise InterpolationMissingOptionError( - option, section, rest, ":".join(path)) + option, section, rawval, ":".join(path)) if "$" in v: self._interpolate_some(parser, opt, accum, v, sect, dict(parser.items(sect, raw=True)), diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -847,7 +847,8 @@ "something with lots of interpolation (10 steps)") e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11") if self.interpolation == configparser._UNSET: - self.assertEqual(e.args, ("bar11", "Foo", "%(with1)s")) + self.assertEqual(e.args, ("bar11", "Foo", + "something %(with11)s lots of interpolation (11 steps)")) elif isinstance(self.interpolation, configparser.LegacyInterpolation): self.assertEqual(e.args, ("bar11", "Foo", "something %(with11)s lots of interpolation (11 steps)")) @@ -861,7 +862,7 @@ self.assertEqual(e.option, "name") if self.interpolation == configparser._UNSET: self.assertEqual(e.args, ('name', 'Interpolation Error', - '', 'reference')) + '%(reference)s', 'reference')) elif isinstance(self.interpolation, configparser.LegacyInterpolation): self.assertEqual(e.args, ('name', 'Interpolation Error', '%(reference)s', 'reference')) @@ -1177,7 +1178,7 @@ with self.assertRaises(exception_class) as cm: cf['interpolated']['$trying'] self.assertEqual(cm.exception.reference, 'dollars:${sick') - self.assertEqual(cm.exception.args[2], '}') #rawval + self.assertEqual(cm.exception.args[2], '${dollars:${sick}}') #rawval def test_case_sensitivity_basic(self): ini = textwrap.dedent(""" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -75,6 +75,9 @@ Library ------- +- Issue #21159: Improve message in configparser.InterpolationMissingOptionError. + Patch from ?ukasz Langa. + - Issue #23888: Handle fractional time in cookie expiry. Patch by ssh. - Issue #23004: mock_open() now reads binary data correctly when the type of -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 01:50:36 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 13 Aug 2015 23:50:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321159=3A_Improve_?= =?utf-8?q?message_in_configparser=2EInterpolationMissingOptionError=2E?= Message-ID: <20150813235035.10874.61503@psf.io> https://hg.python.org/cpython/rev/fb4e67040779 changeset: 97375:fb4e67040779 parent: 97372:23c6cc5d5b8f user: Robert Collins date: Fri Aug 14 11:50:14 2015 +1200 summary: Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Library ------- +- Issue #21159: Improve message in configparser.InterpolationMissingOptionError. + Patch from ?ukasz Langa. + - Issue #20059: urllib.parse raises ValueError on all invalid ports. Patch by Martin Panter. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 06:53:12 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 14 Aug 2015 04:53:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_add_missing_NU?= =?utf-8?q?LL_checks_to_get=5Fcoding=5Fspec_=28closes_=2324854=29?= Message-ID: <20150814045312.7957.94781@psf.io> https://hg.python.org/cpython/rev/208d6d14c2a3 changeset: 97376:208d6d14c2a3 branch: 2.7 parent: 97365:d9c85b6bab3a user: Benjamin Peterson date: Thu Aug 13 21:52:56 2015 -0700 summary: add missing NULL checks to get_coding_spec (closes #24854) files: Parser/tokenizer.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -235,7 +235,10 @@ if (begin < t) { char* r = new_string(begin, t - begin); - char* q = get_normal_name(r); + char* q; + if (!r) + return NULL; + q = get_normal_name(r); if (r != q) { PyMem_FREE(r); r = new_string(q, strlen(q)); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 10:16:24 2015 From: python-checkins at python.org (robert.collins) Date: Fri, 14 Aug 2015 08:16:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321159=3A_Improve_message_in_configparser=2EInte?= =?utf-8?q?rpolationMissingOptionError=2E?= Message-ID: <20150814081624.28823.68317@psf.io> https://hg.python.org/cpython/rev/7191910aeb45 changeset: 97377:7191910aeb45 parent: 97375:fb4e67040779 parent: 97374:1a144ff2d78b user: Robert Collins date: Fri Aug 14 20:16:14 2015 +1200 summary: Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. files: Lib/configparser.py | 29 +++++++++++----------- Lib/test/test_configparser.py | 7 +++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Lib/configparser.py b/Lib/configparser.py --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -263,12 +263,9 @@ """A string substitution required a setting which was not available.""" def __init__(self, option, section, rawval, reference): - msg = ("Bad value substitution:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\tkey : %s\n" - "\trawval : %s\n" - % (section, option, reference, rawval)) + msg = ("Bad value substitution: option {!r} in section {!r} contains " + "an interpolation key {!r} which is not a valid option name. " + "Raw value: {!r}".format(option, section, reference, rawval)) InterpolationError.__init__(self, option, section, msg) self.reference = reference self.args = (option, section, rawval, reference) @@ -286,11 +283,11 @@ """Raised when substitutions are nested too deeply.""" def __init__(self, option, section, rawval): - msg = ("Value interpolation too deeply recursive:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\trawval : %s\n" - % (section, option, rawval)) + msg = ("Recursion limit exceeded in value substitution: option {!r} " + "in section {!r} contains an interpolation key which " + "cannot be substituted in {} steps. Raw value: {!r}" + "".format(option, section, MAX_INTERPOLATION_DEPTH, + rawval)) InterpolationError.__init__(self, option, section, msg) self.args = (option, section, rawval) @@ -406,8 +403,9 @@ def _interpolate_some(self, parser, option, accum, rest, section, map, depth): + rawval = parser.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) + raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("%") if p < 0: @@ -432,7 +430,7 @@ v = map[var] except KeyError: raise InterpolationMissingOptionError( - option, section, rest, var) from None + option, section, rawval, var) from None if "%" in v: self._interpolate_some(parser, option, accum, v, section, map, depth + 1) @@ -466,8 +464,9 @@ def _interpolate_some(self, parser, option, accum, rest, section, map, depth): + rawval = parser.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: - raise InterpolationDepthError(option, section, rest) + raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("$") if p < 0: @@ -504,7 +503,7 @@ "More than one ':' found: %r" % (rest,)) except (KeyError, NoSectionError, NoOptionError): raise InterpolationMissingOptionError( - option, section, rest, ":".join(path)) from None + option, section, rawval, ":".join(path)) from None if "$" in v: self._interpolate_some(parser, opt, accum, v, sect, dict(parser.items(sect, raw=True)), diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -847,7 +847,8 @@ "something with lots of interpolation (10 steps)") e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11") if self.interpolation == configparser._UNSET: - self.assertEqual(e.args, ("bar11", "Foo", "%(with1)s")) + self.assertEqual(e.args, ("bar11", "Foo", + "something %(with11)s lots of interpolation (11 steps)")) elif isinstance(self.interpolation, configparser.LegacyInterpolation): self.assertEqual(e.args, ("bar11", "Foo", "something %(with11)s lots of interpolation (11 steps)")) @@ -861,7 +862,7 @@ self.assertEqual(e.option, "name") if self.interpolation == configparser._UNSET: self.assertEqual(e.args, ('name', 'Interpolation Error', - '', 'reference')) + '%(reference)s', 'reference')) elif isinstance(self.interpolation, configparser.LegacyInterpolation): self.assertEqual(e.args, ('name', 'Interpolation Error', '%(reference)s', 'reference')) @@ -1177,7 +1178,7 @@ with self.assertRaises(exception_class) as cm: cf['interpolated']['$trying'] self.assertEqual(cm.exception.reference, 'dollars:${sick') - self.assertEqual(cm.exception.args[2], '}') #rawval + self.assertEqual(cm.exception.args[2], '${dollars:${sick}}') #rawval def test_case_sensitivity_basic(self): ini = textwrap.dedent(""" -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Fri Aug 14 10:40:32 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Fri, 14 Aug 2015 08:40:32 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-14 Message-ID: Results for project python_default-nightly, build date 2015-08-14 09:02:12 commit: fb4e6704077902dfe3a2380346ae8508a4c13b23 revision date: 2015-08-14 02:50:14 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec -0.11196% -2.12426% :-) regex_v8 sec 4.28656% -3.45168% :-| nbody sec 0.87412% -1.14195% :-) json_dump_v2 sec 3.11894% -0.55292% :-| normal_startup sec -0.06852% -0.07084% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Fri Aug 14 11:20:04 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 14 Aug 2015 09:20:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_cleanup=2E?= Message-ID: <20150814090752.59451.54889@psf.io> https://hg.python.org/cpython/rev/a1daf32d920e changeset: 97378:a1daf32d920e user: Raymond Hettinger date: Fri Aug 14 02:07:41 2015 -0700 summary: Minor cleanup. files: Modules/_collectionsmodule.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2167,13 +2167,13 @@ oldval = _PyDict_GetItem_KnownHash(mapping, key, hash); if (oldval == NULL) { - if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) == -1) + if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) < 0) goto done; } else { newval = PyNumber_Add(oldval, one); if (newval == NULL) goto done; - if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) == -1) + if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) < 0) goto done; Py_CLEAR(newval); } @@ -2199,7 +2199,7 @@ Py_DECREF(oldval); if (newval == NULL) break; - if (PyObject_SetItem(mapping, key, newval) == -1) + if (PyObject_SetItem(mapping, key, newval) < 0) break; Py_CLEAR(newval); Py_DECREF(key); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 20:10:22 2015 From: python-checkins at python.org (brett.cannon) Date: Fri, 14 Aug 2015 18:10:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NDky?= =?utf-8?b?OiBtYWtlIHN1cmUgdGhhdCBgYGZyb20gLi4uIGltcG9ydCAuLi5gIHJhaXNl?= =?utf-8?q?s_an?= Message-ID: <20150814181021.15623.96800@psf.io> https://hg.python.org/cpython/rev/cf3a62a8d786 changeset: 97379:cf3a62a8d786 branch: 3.5 parent: 97356:399362d0e504 user: Brett Cannon date: Tue Aug 11 18:01:31 2015 -0700 summary: Issue #24492: make sure that ``from ... import ...` raises an ImportError if __name__ is not defined on a package. Thanks to Armin Rigo for the bug report and diagnosing the cause. files: Lib/test/test_import/__init__.py | 13 +++++++++++++ Misc/NEWS | 4 ++++ Python/ceval.c | 19 ++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -324,6 +324,19 @@ with self.assertRaisesRegex(ImportError, "^cannot import name 'bogus'"): from re import bogus + def test_from_import_AttributeError(self): + # Issue #24492: trying to import an attribute that raises an + # AttributeError should lead to an ImportError. + class AlwaysAttributeError: + def __getattr__(self, _): + raise AttributeError + + module_name = 'test_from_import_AttributeError' + self.addCleanup(unload, module_name) + sys.modules[module_name] = AlwaysAttributeError() + with self.assertRaises(ImportError): + from test_from_import_AttributeError import does_not_exist + @skip_if_dont_write_bytecode class FilePermissionTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24492: A "package" lacking a __name__ attribute when trying to perform + a ``from .. import ...`` statement will trigger an ImportError instead of an + AttributeError. + - Issue #24667: Resize odict in all cases that the underlying dict resizes. Library diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5085,19 +5085,24 @@ sys.modules. */ PyErr_Clear(); pkgname = _PyObject_GetAttrId(v, &PyId___name__); - if (pkgname == NULL) - return NULL; + if (pkgname == NULL) { + goto error; + } fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name); Py_DECREF(pkgname); - if (fullmodname == NULL) + if (fullmodname == NULL) { return NULL; + } x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname); - if (x == NULL) - PyErr_Format(PyExc_ImportError, "cannot import name %R", name); - else - Py_INCREF(x); Py_DECREF(fullmodname); + if (x == NULL) { + goto error; + } + Py_INCREF(x); return x; + error: + PyErr_Format(PyExc_ImportError, "cannot import name %R", name); + return NULL; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 20:10:30 2015 From: python-checkins at python.org (brett.cannon) Date: Fri, 14 Aug 2015 18:10:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge_from_3=2E5=2E0_for_issue_=2324492?= Message-ID: <20150814181027.36731.17356@psf.io> https://hg.python.org/cpython/rev/bbe6b215df5d changeset: 97380:bbe6b215df5d branch: 3.5 parent: 97374:1a144ff2d78b parent: 97379:cf3a62a8d786 user: Brett Cannon date: Fri Aug 14 11:06:43 2015 -0700 summary: Merge from 3.5.0 for issue #24492 files: Lib/test/test_import/__init__.py | 13 +++++++++++++ Misc/NEWS | 4 ++++ Python/ceval.c | 19 ++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -324,6 +324,19 @@ with self.assertRaisesRegex(ImportError, "^cannot import name 'bogus'"): from re import bogus + def test_from_import_AttributeError(self): + # Issue #24492: trying to import an attribute that raises an + # AttributeError should lead to an ImportError. + class AlwaysAttributeError: + def __getattr__(self, _): + raise AttributeError + + module_name = 'test_from_import_AttributeError' + self.addCleanup(unload, module_name) + sys.modules[module_name] = AlwaysAttributeError() + with self.assertRaises(ImportError): + from test_from_import_AttributeError import does_not_exist + @skip_if_dont_write_bytecode class FilePermissionTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,10 @@ Core and Builtins ----------------- +- Issue #24492: A "package" lacking a __name__ attribute when trying to perform + a ``from .. import ...`` statement will trigger an ImportError instead of an + AttributeError. + - Issue #24667: Resize odict in all cases that the underlying dict resizes. Library diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5085,19 +5085,24 @@ sys.modules. */ PyErr_Clear(); pkgname = _PyObject_GetAttrId(v, &PyId___name__); - if (pkgname == NULL) - return NULL; + if (pkgname == NULL) { + goto error; + } fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name); Py_DECREF(pkgname); - if (fullmodname == NULL) + if (fullmodname == NULL) { return NULL; + } x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname); - if (x == NULL) - PyErr_Format(PyExc_ImportError, "cannot import name %R", name); - else - Py_INCREF(x); Py_DECREF(fullmodname); + if (x == NULL) { + goto error; + } + Py_INCREF(x); return x; + error: + PyErr_Format(PyExc_ImportError, "cannot import name %R", name); + return NULL; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 20:10:30 2015 From: python-checkins at python.org (brett.cannon) Date: Fri, 14 Aug 2015 18:10:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E5_for_issue_=2324492?= Message-ID: <20150814181027.6804.77472@psf.io> https://hg.python.org/cpython/rev/b0a6bba16b9c changeset: 97381:b0a6bba16b9c parent: 97378:a1daf32d920e parent: 97380:bbe6b215df5d user: Brett Cannon date: Fri Aug 14 11:09:56 2015 -0700 summary: Merge from 3.5 for issue #24492 files: Lib/test/test_import/__init__.py | 13 +++++++++++++ Python/ceval.c | 19 ++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -324,6 +324,19 @@ with self.assertRaisesRegex(ImportError, "^cannot import name 'bogus'"): from re import bogus + def test_from_import_AttributeError(self): + # Issue #24492: trying to import an attribute that raises an + # AttributeError should lead to an ImportError. + class AlwaysAttributeError: + def __getattr__(self, _): + raise AttributeError + + module_name = 'test_from_import_AttributeError' + self.addCleanup(unload, module_name) + sys.modules[module_name] = AlwaysAttributeError() + with self.assertRaises(ImportError): + from test_from_import_AttributeError import does_not_exist + @skip_if_dont_write_bytecode class FilePermissionTests(unittest.TestCase): diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5085,19 +5085,24 @@ sys.modules. */ PyErr_Clear(); pkgname = _PyObject_GetAttrId(v, &PyId___name__); - if (pkgname == NULL) - return NULL; + if (pkgname == NULL) { + goto error; + } fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name); Py_DECREF(pkgname); - if (fullmodname == NULL) + if (fullmodname == NULL) { return NULL; + } x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname); - if (x == NULL) - PyErr_Format(PyExc_ImportError, "cannot import name %R", name); - else - Py_INCREF(x); Py_DECREF(fullmodname); + if (x == NULL) { + goto error; + } + Py_INCREF(x); return x; + error: + PyErr_Format(PyExc_ImportError, "cannot import name %R", name); + return NULL; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 21:35:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 14 Aug 2015 19:35:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0ODY3?= =?utf-8?q?=3A_Fix_Task=2Eget=5Fstack=28=29_for_=27async_def=27_coroutines?= Message-ID: <20150814193520.21670.49025@psf.io> https://hg.python.org/cpython/rev/53d2a7c023bc changeset: 97382:53d2a7c023bc branch: 3.4 parent: 97373:267422f7c927 user: Yury Selivanov date: Fri Aug 14 15:30:59 2015 -0400 summary: Issue #24867: Fix Task.get_stack() for 'async def' coroutines files: Lib/asyncio/tasks.py | 6 ++- Lib/test/test_asyncio/test_tasks.py | 32 +++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -128,7 +128,11 @@ returned for a suspended coroutine. """ frames = [] - f = self._coro.gi_frame + try: + # 'async def' coroutines + f = self._coro.cr_frame + except AttributeError: + f = self._coro.gi_frame if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2,6 +2,7 @@ import contextlib import functools +import io import os import re import sys @@ -162,6 +163,37 @@ 'function is deprecated, use ensure_'): self.assertIs(f, asyncio.async(f)) + def test_get_stack(self): + T = None + + @asyncio.coroutine + def foo(): + yield from bar() + + @asyncio.coroutine + def bar(): + # test get_stack() + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + # test print_stack() + file = io.StringIO() + T.print_stack(limit=1, file=file) + file.seek(0) + tb = file.read() + self.assertRegex(tb, r'foo\(\) running') + + @asyncio.coroutine + def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + yield from T + + self.loop.run_until_complete(runner()) + def test_task_repr(self): self.loop.set_debug(False) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 21:35:21 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 14 Aug 2015 19:35:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZSAjMjQ4Njcp?= Message-ID: <20150814193521.4941.63942@psf.io> https://hg.python.org/cpython/rev/c0b7829e3074 changeset: 97384:c0b7829e3074 parent: 97381:b0a6bba16b9c parent: 97383:d25022765186 user: Yury Selivanov date: Fri Aug 14 15:35:14 2015 -0400 summary: Merge 3.5 (issue #24867) files: Lib/asyncio/tasks.py | 6 ++- Lib/test/test_asyncio/test_pep492.py | 17 ++++++++ Lib/test/test_asyncio/test_tasks.py | 32 ++++++++++++++++ Misc/NEWS | 2 + 4 files changed, 56 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -128,7 +128,11 @@ returned for a suspended coroutine. """ frames = [] - f = self._coro.gi_frame + try: + # 'async def' coroutines + f = self._coro.cr_frame + except AttributeError: + f = self._coro.gi_frame if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -186,6 +186,23 @@ data = self.loop.run_until_complete(coro()) self.assertEqual(data, 'spam') + def test_task_print_stack(self): + T = None + + async def foo(): + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + async def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + await T + + self.loop.run_until_complete(runner()) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2,6 +2,7 @@ import contextlib import functools +import io import os import re import sys @@ -162,6 +163,37 @@ 'function is deprecated, use ensure_'): self.assertIs(f, asyncio.async(f)) + def test_get_stack(self): + T = None + + @asyncio.coroutine + def foo(): + yield from bar() + + @asyncio.coroutine + def bar(): + # test get_stack() + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + # test print_stack() + file = io.StringIO() + T.print_stack(limit=1, file=file) + file.seek(0) + tb = file.read() + self.assertRegex(tb, r'foo\(\) running') + + @asyncio.coroutine + def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + yield from T + + self.loop.run_until_complete(runner()) + def test_task_repr(self): self.loop.set_debug(False) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -87,6 +87,8 @@ - Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo functions. +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 21:35:21 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 14 Aug 2015 19:35:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_3=2E4_=28Issue_=2324867=29?= Message-ID: <20150814193520.91833.52551@psf.io> https://hg.python.org/cpython/rev/d25022765186 changeset: 97383:d25022765186 branch: 3.5 parent: 97380:bbe6b215df5d parent: 97382:53d2a7c023bc user: Yury Selivanov date: Fri Aug 14 15:32:37 2015 -0400 summary: Merge 3.4 (Issue #24867) files: Lib/asyncio/tasks.py | 6 ++- Lib/test/test_asyncio/test_pep492.py | 17 ++++++++ Lib/test/test_asyncio/test_tasks.py | 32 ++++++++++++++++ Misc/NEWS | 2 + 4 files changed, 56 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -128,7 +128,11 @@ returned for a suspended coroutine. """ frames = [] - f = self._coro.gi_frame + try: + # 'async def' coroutines + f = self._coro.cr_frame + except AttributeError: + f = self._coro.gi_frame if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -186,6 +186,23 @@ data = self.loop.run_until_complete(coro()) self.assertEqual(data, 'spam') + def test_task_print_stack(self): + T = None + + async def foo(): + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + async def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + await T + + self.loop.run_until_complete(runner()) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2,6 +2,7 @@ import contextlib import functools +import io import os import re import sys @@ -162,6 +163,37 @@ 'function is deprecated, use ensure_'): self.assertIs(f, asyncio.async(f)) + def test_get_stack(self): + T = None + + @asyncio.coroutine + def foo(): + yield from bar() + + @asyncio.coroutine + def bar(): + # test get_stack() + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + # test print_stack() + file = io.StringIO() + T.print_stack(limit=1, file=file) + file.seek(0) + tb = file.read() + self.assertRegex(tb, r'foo\(\) running') + + @asyncio.coroutine + def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + yield from T + + self.loop.run_until_complete(runner()) + def test_task_repr(self): self.loop.set_debug(False) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,8 @@ - Issue #24839: platform._syscmd_ver raises DeprecationWarning +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 22:13:39 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 14 Aug 2015 20:13:39 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Closes_=2317570=3A_Improv?= =?utf-8?q?e_instructions_for_Windows=2E?= Message-ID: <20150814201339.4927.55264@psf.io> https://hg.python.org/devguide/rev/49be7fba3568 changeset: 761:49be7fba3568 user: Zachary Ware date: Fri Aug 14 15:12:28 2015 -0500 summary: Closes #17570: Improve instructions for Windows. Inital patch by Volodymyr Bezkostnyy, Carol Willing, and Peter Lovett. files: committing.rst | 52 +++++++++++++++++++++++-------------- patch.rst | 4 +- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/committing.rst b/committing.rst --- a/committing.rst +++ b/committing.rst @@ -36,9 +36,19 @@ Patch checklist ''''''''''''''' -Apart from running the tests, there's a simple patch checklist that -``make patchcheck`` (or ``./python.exe Tools/scripts/patchcheck.py`` on -Windows) will run through: +Along with running the tests, a simple automated patch checklist, `patchcheck`, +guides a developer through the common patch generation checks. To run +`patchcheck`: + + On *UNIX* (including Mac OS X):: + + make patchcheck + + On *Windows* (after any successful build):: + + python.bat Tools/scripts/patchcheck.py + +The automated patch checklist runs through: * Are there any whitespace problems in Python files? (using ``Tools/scripts/reindent.py``) @@ -52,10 +62,9 @@ * Has ``configure`` been regenerated, if necessary? * Has ``pyconfig.h.in`` been regenerated, if necessary? -Note that the automated patch check can't actually *answer* all of these -questions, and even if it could, it still wouldn't know whether or not -those answers were appropriate. Aside from the whitespace checks, it is just -a memory aid to help with remembering the various elements that can go into +The automated patch check doesn't actually *answer* all of these +questions. Aside from the whitespace checks, the tool is +a memory aid for the various elements that can go into making a complete patch. @@ -274,12 +283,14 @@ Minimal Configuration --------------------- -To use Mercurial as a committer (both of your and others' patches), you should -set up some basic options in your `configuration file`_. Under Windows, -TortoiseHg has a graphical settings dialog for most options, meaning you -don't need to edit the file directly (it is still available in -``%USERPROFILE%\Mercurial.ini``). Under other platforms, you must edit -``~/.hgrc``. +If you use Mercurial as a committer of patches (your own or others), you should +set up some basic options in your `configuration file`_. + +* On *UNIX* (including Mac OS X), you must edit ``~/.hgrc``. +* Under *Windows*, use TortoiseHg's graphical settings dialog to make changes + to ``mercurial.ini``. Alternatively, you may edit the file directly at + ``%USERPROFILE%\mercurial.ini``. + Here are the minimal options you need to activate: @@ -298,11 +309,11 @@ [diff] git = on -Under Windows, you should also enable the `eol extension`_, which will -fix any Windows-specific line endings your text editor might insert when you -create or modify versioned files. The public repository has a hook which -will reject all changesets having the wrong line endings, so enabling this -extension on your local computer is in your best interest. +* *Under Windows*, you should also enable the `eol extension`_, which will + fix any Windows-specific line endings your text editor might insert when you + create or modify versioned files. The public repository has a hook which + will reject all changesets having the wrong line endings, so enabling this + extension on your local computer is in your best interest. As a core developer, it can be very helpful to set up the same commit checks locally that the main repo enforces for incoming patch sets. This can save a @@ -312,7 +323,7 @@ Configuring and using the whitespace checking hook found in the `hooks repository`_ will help check incoming patch sets. To configure a hook, -add configuration settings to ``~/.hgrc`` for the relevant repo(s) (remember +add configuration settings to ``.hg/hgrc`` for the relevant repo(s) (remember to adjust the path appropriately for the checked out location of the `hooks repository`_). To configure a "pretxncommit" hook that will check whitespace before the changeset is committed and can thus abort the commit @@ -363,7 +374,8 @@ developers. The easiest way to do this is by using the `share extension`_, that can be -enabled by adding the following lines to your ``~/.hgrc``:: +enabled by adding the following lines to your ``~/.hgrc`` (``mercurial.ini`` +on Windows):: [extensions] share = diff --git a/patch.rst b/patch.rst --- a/patch.rst +++ b/patch.rst @@ -90,9 +90,9 @@ This will check and/or fix various common things people forget to do for patches, such as adding any new files needed for the patch to work (note that not all checks apply to non-core developers). On Windows, use this -command:: +command (after any successful build of Python):: - ./python.exe Tools/scripts/patchcheck.py + python.bat Tools/scripts/patchcheck.py Assuming you are using the :ref:`basic approach ` suggested earlier, just type the following:: -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Fri Aug 14 23:00:31 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 14 Aug 2015 21:00:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150814210029.6310.2720@psf.io> https://hg.python.org/cpython/rev/310ec12daa7d changeset: 97388:310ec12daa7d parent: 97384:c0b7829e3074 parent: 97387:69a8b05f27b4 user: Terry Jan Reedy date: Fri Aug 14 17:00:12 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/ScriptBinding.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -69,7 +69,7 @@ try: tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError as msg: - msgtxt, (lineno, start) = msg + msgtxt, (lineno, start) = msg.args self.editwin.gotoline(lineno) self.errorbox("Tabnanny Tokenizing Error", "Token Error: %s" % msgtxt) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 23:00:31 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 14 Aug 2015 21:00:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0ODMz?= =?utf-8?q?=3A_Add_attribute_reference_needed_for_3=2Ex=2E?= Message-ID: <20150814210028.13742.53003@psf.io> https://hg.python.org/cpython/rev/cce226356477 changeset: 97386:cce226356477 branch: 3.4 parent: 97382:53d2a7c023bc user: Terry Jan Reedy date: Fri Aug 14 16:59:42 2015 -0400 summary: Issue #24833: Add attribute reference needed for 3.x. files: Lib/idlelib/ScriptBinding.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -69,7 +69,7 @@ try: tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError as msg: - msgtxt, (lineno, start) = msg + msgtxt, (lineno, start) = msg.args self.editwin.gotoline(lineno) self.errorbox("Tabnanny Tokenizing Error", "Token Error: %s" % msgtxt) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 23:00:36 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 14 Aug 2015 21:00:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150814210029.33210.11125@psf.io> https://hg.python.org/cpython/rev/69a8b05f27b4 changeset: 97387:69a8b05f27b4 branch: 3.5 parent: 97383:d25022765186 parent: 97386:cce226356477 user: Terry Jan Reedy date: Fri Aug 14 16:59:58 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/ScriptBinding.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -69,7 +69,7 @@ try: tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError as msg: - msgtxt, (lineno, start) = msg + msgtxt, (lineno, start) = msg.args self.editwin.gotoline(lineno) self.errorbox("Tabnanny Tokenizing Error", "Token Error: %s" % msgtxt) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 23:00:36 2015 From: python-checkins at python.org (terry.reedy) Date: Fri, 14 Aug 2015 21:00:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0ODMz?= =?utf-8?q?=3A_Add_attribute_reference_needed_for_3=2Ex=2C_but_optional_fo?= =?utf-8?b?ciAyLjcs?= Message-ID: <20150814210028.33438.49890@psf.io> https://hg.python.org/cpython/rev/724d9b589cfc changeset: 97385:724d9b589cfc branch: 2.7 parent: 97376:208d6d14c2a3 user: Terry Jan Reedy date: Fri Aug 14 16:59:36 2015 -0400 summary: Issue #24833: Add attribute reference needed for 3.x, but optional for 2.7, to keep synchronized. files: Lib/idlelib/ScriptBinding.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -71,7 +71,7 @@ try: tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError as msg: - msgtxt, (lineno, start) = msg + msgtxt, (lineno, start) = msg.args self.editwin.gotoline(lineno) self.errorbox("Tabnanny Tokenizing Error", "Token Error: %s" % msgtxt) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 14 23:10:53 2015 From: python-checkins at python.org (raymond.hettinger) Date: Fri, 14 Aug 2015 21:10:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Neaten-up_vertical_alignme?= =?utf-8?q?nt_of_comments?= Message-ID: <20150814211053.6792.55648@psf.io> https://hg.python.org/cpython/rev/96d016f78726 changeset: 97389:96d016f78726 user: Raymond Hettinger date: Fri Aug 14 14:10:49 2015 -0700 summary: Neaten-up vertical alignment of comments files: Modules/itertoolsmodule.c | 124 +++++++++++++------------- 1 files changed, 62 insertions(+), 62 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -178,7 +178,7 @@ reduce_doc}, {"__setstate__", (PyCFunction)groupby_setstate, METH_O, setstate_doc}, - {NULL, NULL} /* sentinel */ + {NULL, NULL} /* sentinel */ }; PyDoc_STRVAR(groupby_doc, @@ -364,7 +364,7 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)_grouper_traverse,/* tp_traverse */ + (traverseproc)_grouper_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -582,7 +582,7 @@ PyDoc_STRVAR(teedataobject_doc, "Data container common to multiple tee objects."); static PyTypeObject teedataobject_type = { - PyVarObject_HEAD_INIT(0, 0) /* Must fill in type value later */ + PyVarObject_HEAD_INIT(0, 0) /* Must fill in type value later */ "itertools._tee_dataobject", /* tp_name */ sizeof(teedataobject), /* tp_basicsize */ 0, /* tp_itemsize */ @@ -602,7 +602,7 @@ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ teedataobject_doc, /* tp_doc */ (traverseproc)teedataobject_traverse, /* tp_traverse */ (inquiry)teedataobject_clear, /* tp_clear */ @@ -791,7 +791,7 @@ (traverseproc)tee_traverse, /* tp_traverse */ (inquiry)tee_clear, /* tp_clear */ 0, /* tp_richcompare */ - offsetof(teeobject, weakreflist), /* tp_weaklistoffset */ + offsetof(teeobject, weakreflist), /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)tee_next, /* tp_iternext */ tee_methods, /* tp_methods */ @@ -1189,13 +1189,13 @@ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ dropwhile_doc, /* tp_doc */ - (traverseproc)dropwhile_traverse, /* tp_traverse */ + (traverseproc)dropwhile_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)dropwhile_next, /* tp_iternext */ - dropwhile_methods, /* tp_methods */ + dropwhile_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1353,7 +1353,7 @@ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ takewhile_doc, /* tp_doc */ - (traverseproc)takewhile_traverse, /* tp_traverse */ + (traverseproc)takewhile_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -2287,7 +2287,7 @@ static PyTypeObject product_type = { PyVarObject_HEAD_INIT(NULL, 0) "itertools.product", /* tp_name */ - sizeof(productobject), /* tp_basicsize */ + sizeof(productobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)product_dealloc, /* tp_dealloc */ @@ -2334,8 +2334,8 @@ typedef struct { PyObject_HEAD PyObject *pool; /* input converted to a tuple */ - Py_ssize_t *indices; /* one index per result element */ - PyObject *result; /* most recently returned result tuple */ + Py_ssize_t *indices; /* one index per result element */ + PyObject *result; /* most recently returned result tuple */ Py_ssize_t r; /* size of result tuple */ int stopped; /* set to 1 when the combinations iterator is exhausted */ } combinationsobject; @@ -2675,8 +2675,8 @@ typedef struct { PyObject_HEAD PyObject *pool; /* input converted to a tuple */ - Py_ssize_t *indices; /* one index per result element */ - PyObject *result; /* most recently returned result tuple */ + Py_ssize_t *indices; /* one index per result element */ + PyObject *result; /* most recently returned result tuple */ Py_ssize_t r; /* size of result tuple */ int stopped; /* set to 1 when the cwr iterator is exhausted */ } cwrobject; @@ -3326,11 +3326,11 @@ static PyTypeObject permutations_type = { PyVarObject_HEAD_INIT(NULL, 0) - "itertools.permutations", /* tp_name */ + "itertools.permutations", /* tp_name */ sizeof(permutationsobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)permutations_dealloc, /* tp_dealloc */ + (destructor)permutations_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -3347,13 +3347,13 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ - permutations_doc, /* tp_doc */ - (traverseproc)permutations_traverse, /* tp_traverse */ + permutations_doc, /* tp_doc */ + (traverseproc)permutations_traverse,/* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)permutations_next, /* tp_iternext */ + (iternextfunc)permutations_next, /* tp_iternext */ permuations_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ @@ -3364,7 +3364,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - permutations_new, /* tp_new */ + permutations_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; @@ -3664,44 +3664,44 @@ PyVarObject_HEAD_INIT(NULL, 0) "itertools.compress", /* tp_name */ sizeof(compressobject), /* tp_basicsize */ - 0, /* tp_itemsize */ + 0, /* tp_itemsize */ /* methods */ (destructor)compress_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - compress_doc, /* tp_doc */ - (traverseproc)compress_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ + compress_doc, /* tp_doc */ + (traverseproc)compress_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ (iternextfunc)compress_next, /* tp_iternext */ - compress_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - compress_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + compress_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + compress_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; @@ -3824,7 +3824,7 @@ sizeof(filterfalseobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)filterfalse_dealloc, /* tp_dealloc */ + (destructor)filterfalse_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -3842,7 +3842,7 @@ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ filterfalse_doc, /* tp_doc */ - (traverseproc)filterfalse_traverse, /* tp_traverse */ + (traverseproc)filterfalse_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -4081,15 +4081,15 @@ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ count_doc, /* tp_doc */ - (traverseproc)count_traverse, /* tp_traverse */ + (traverseproc)count_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)count_next, /* tp_iternext */ - count_methods, /* tp_methods */ + count_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -4488,7 +4488,7 @@ sizeof(ziplongestobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)zip_longest_dealloc, /* tp_dealloc */ + (destructor)zip_longest_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -4505,8 +4505,8 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ - zip_longest_doc, /* tp_doc */ - (traverseproc)zip_longest_traverse, /* tp_traverse */ + zip_longest_doc, /* tp_doc */ + (traverseproc)zip_longest_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -4522,7 +4522,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - zip_longest_new, /* tp_new */ + zip_longest_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 15 22:52:07 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 15 Aug 2015 20:52:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_crash_in_itertools=2Ec?= =?utf-8?q?ycle=2E=5F=5Fsetstate=5F=5F=28=29_caused_by_lack_of_type_checki?= =?utf-8?b?bmcu?= Message-ID: <20150815205207.33505.2351@psf.io> https://hg.python.org/cpython/rev/a4d5ef7fdec3 changeset: 97390:a4d5ef7fdec3 user: Raymond Hettinger date: Sat Aug 15 13:51:59 2015 -0700 summary: Fix crash in itertools.cycle.__setstate__() caused by lack of type checking. Will backport after the 3.6 release is done. files: Lib/test/test_itertools.py | 33 ++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/itertoolsmodule.c | 2 +- 3 files changed, 37 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -613,6 +613,39 @@ for proto in range(pickle.HIGHEST_PROTOCOL + 1): self.pickletest(proto, cycle('abc')) + def test_cycle_setstate(self): + # Verify both modes for restoring state + + # Mode 0 is efficient. It uses an incompletely consumed input + # iterator to build a cycle object and then passes in state with + # a list of previously consumed values. There is no data + # overlap bewteen the two. + c = cycle('defg') + c.__setstate__((list('abc'), 0)) + self.assertEqual(take(20, c), list('defgabcdefgabcdefgab')) + + # Mode 1 is inefficient. It starts with a cycle object built + # from an iterator over the remaining elements in a partial + # cycle and then passes in state with all of the previously + # seen values (this overlaps values included in the iterator). + c = cycle('defg') + c.__setstate__((list('abcdefg'), 1)) + self.assertEqual(take(20, c), list('defgabcdefgabcdefgab')) + + # The first argument to setstate needs to be a tuple + with self.assertRaises(SystemError): + cycle('defg').__setstate__([list('abcdefg'), 0]) + + # The first argument in the setstate tuple must be a list + with self.assertRaises(TypeError): + c = cycle('defg') + c.__setstate__((dict.fromkeys('defg'), 0)) + take(20, c) + + # The first argument in the setstate tuple must be a list + with self.assertRaises(TypeError): + cycle('defg').__setstate__((list('abcdefg'), 'x')) + def test_groupby(self): # Check whether it accepts arguments correctly self.assertEqual([], list(groupby([]))) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,9 @@ - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. +- Fix crash in itertools.cycle.__setstate__() when the first argument wasn't + a list. + - Issue #20059: urllib.parse raises ValueError on all invalid ports. Patch by Martin Panter. diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -973,7 +973,7 @@ { PyObject *saved=NULL; int firstpass; - if (!PyArg_ParseTuple(state, "Oi", &saved, &firstpass)) + if (!PyArg_ParseTuple(state, "O!i", &PyList_Type, &saved, &firstpass)) return NULL; Py_CLEAR(lz->saved); lz->saved = saved; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 15 23:38:47 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 15 Aug 2015 21:38:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150815213847.21654.59760@psf.io> https://hg.python.org/cpython/rev/176fb8e8ca19 changeset: 97392:176fb8e8ca19 parent: 97390:a4d5ef7fdec3 parent: 97391:70d422efa742 user: Steve Dower date: Sat Aug 15 14:38:29 2015 -0700 summary: Merge with 3.5 files: Tools/msi/build.bat | 8 +++++++- Tools/msi/bundle/snapshot.wixproj | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -7,6 +7,7 @@ set BUILDX64= set BUILDDOC= set BUILDPX= +set BUILDPACK= :CheckOpts if "%~1" EQU "-h" goto Help @@ -14,6 +15,7 @@ if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if "%~1" EQU "--test-marker" (set BUILDPX=1) && shift && goto CheckOpts +if "%~1" EQU "--pack" (set BUILDPACK=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -41,6 +43,9 @@ if defined BUILDPX ( set BUILD_CMD=%BUILD_CMD% /p:UseTestMarker=true ) +if defined BUILDPACK ( + set BUILD_CMD=%BUILD_CMD% /p:Pack=true +) if defined BUILDX86 ( "%PCBUILD%win32\python.exe" "%D%get_wix.py" @@ -56,9 +61,10 @@ exit /B 0 :Help -echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] +echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] [--pack] echo. echo -x86 Build x86 installers echo -x64 Build x64 installers echo --doc Build CHM documentation echo --test-marker Build installers with 'x' markers +echo --pack Embed core MSIs into installer diff --git a/Tools/msi/bundle/snapshot.wixproj b/Tools/msi/bundle/snapshot.wixproj --- a/Tools/msi/bundle/snapshot.wixproj +++ b/Tools/msi/bundle/snapshot.wixproj @@ -9,9 +9,14 @@ + + $(DefineConstants);CompressMSI=no; + + + $(DefineConstants);CompressMSI=yes; + $(DefineConstants); - CompressMSI=no; CompressPDB=no; CompressMSI_D=no; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 15 23:38:47 2015 From: python-checkins at python.org (steve.dower) Date: Sat, 15 Aug 2015 21:38:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Enables_buildi?= =?utf-8?q?ng_compressed_Windows_test_builds_with_--pack_option=2E?= Message-ID: <20150815213847.6777.79816@psf.io> https://hg.python.org/cpython/rev/70d422efa742 changeset: 97391:70d422efa742 branch: 3.5 parent: 97387:69a8b05f27b4 user: Steve Dower date: Sat Aug 15 14:38:16 2015 -0700 summary: Enables building compressed Windows test builds with --pack option. files: Tools/msi/build.bat | 8 +++++++- Tools/msi/bundle/snapshot.wixproj | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -7,6 +7,7 @@ set BUILDX64= set BUILDDOC= set BUILDPX= +set BUILDPACK= :CheckOpts if "%~1" EQU "-h" goto Help @@ -14,6 +15,7 @@ if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts if "%~1" EQU "--test-marker" (set BUILDPX=1) && shift && goto CheckOpts +if "%~1" EQU "--pack" (set BUILDPACK=1) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1) @@ -41,6 +43,9 @@ if defined BUILDPX ( set BUILD_CMD=%BUILD_CMD% /p:UseTestMarker=true ) +if defined BUILDPACK ( + set BUILD_CMD=%BUILD_CMD% /p:Pack=true +) if defined BUILDX86 ( "%PCBUILD%win32\python.exe" "%D%get_wix.py" @@ -56,9 +61,10 @@ exit /B 0 :Help -echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] +echo build.bat [-x86] [-x64] [--doc] [-h] [--test-marker] [--pack] echo. echo -x86 Build x86 installers echo -x64 Build x64 installers echo --doc Build CHM documentation echo --test-marker Build installers with 'x' markers +echo --pack Embed core MSIs into installer diff --git a/Tools/msi/bundle/snapshot.wixproj b/Tools/msi/bundle/snapshot.wixproj --- a/Tools/msi/bundle/snapshot.wixproj +++ b/Tools/msi/bundle/snapshot.wixproj @@ -9,9 +9,14 @@ + + $(DefineConstants);CompressMSI=no; + + + $(DefineConstants);CompressMSI=yes; + $(DefineConstants); - CompressMSI=no; CompressPDB=no; CompressMSI_D=no; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 15 23:46:16 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 15 Aug 2015 21:46:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_more_tests_for_picklin?= =?utf-8?q?g_itertools=2Ecycle?= Message-ID: <20150815214612.47402.97787@psf.io> https://hg.python.org/cpython/rev/f6cc89b87ee3 changeset: 97393:f6cc89b87ee3 user: Raymond Hettinger date: Sat Aug 15 14:45:49 2015 -0700 summary: Add more tests for pickling itertools.cycle files: Lib/test/test_itertools.py | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -613,6 +613,23 @@ for proto in range(pickle.HIGHEST_PROTOCOL + 1): self.pickletest(proto, cycle('abc')) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + # test with partial consumed input iterable + it = iter('abcde') + c = cycle(it) + _ = [next(c) for i in range(2)] # consume to 2 of 5 inputs + p = pickle.dumps(c, proto) + d = pickle.loads(p) # rebuild the cycle object + self.assertEqual(take(20, d), list('cdeabcdeabcdeabcdeab')) + + # test with completely consumed input iterable + it = iter('abcde') + c = cycle(it) + _ = [next(c) for i in range(7)] # consume to 7 of 5 inputs + p = pickle.dumps(c, proto) + d = pickle.loads(p) # rebuild the cycle object + self.assertEqual(take(20, d), list('cdeabcdeabcdeabcdeab')) + def test_cycle_setstate(self): # Verify both modes for restoring state -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 15 23:47:49 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 15 Aug 2015 21:47:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Improve_comment?= Message-ID: <20150815214749.47420.95160@psf.io> https://hg.python.org/cpython/rev/b2ab401be73a changeset: 97394:b2ab401be73a user: Raymond Hettinger date: Sat Aug 15 14:47:27 2015 -0700 summary: Improve comment files: Lib/test/test_itertools.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -617,7 +617,7 @@ # test with partial consumed input iterable it = iter('abcde') c = cycle(it) - _ = [next(c) for i in range(2)] # consume to 2 of 5 inputs + _ = [next(c) for i in range(2)] # consume 2 of 5 inputs p = pickle.dumps(c, proto) d = pickle.loads(p) # rebuild the cycle object self.assertEqual(take(20, d), list('cdeabcdeabcdeabcdeab')) @@ -625,7 +625,7 @@ # test with completely consumed input iterable it = iter('abcde') c = cycle(it) - _ = [next(c) for i in range(7)] # consume to 7 of 5 inputs + _ = [next(c) for i in range(7)] # consume 7 of 5 inputs p = pickle.dumps(c, proto) d = pickle.loads(p) # rebuild the cycle object self.assertEqual(take(20, d), list('cdeabcdeabcdeabcdeab')) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 16 00:09:36 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 15 Aug 2015 22:09:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_dead_code_=28unreac?= =?utf-8?q?hable=29?= Message-ID: <20150815220935.36741.3257@psf.io> https://hg.python.org/cpython/rev/d67e2b7314b5 changeset: 97395:d67e2b7314b5 user: Raymond Hettinger date: Sat Aug 15 15:09:30 2015 -0700 summary: Remove dead code (unreachable) files: Modules/itertoolsmodule.c | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -940,12 +940,9 @@ } return item; } - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else + /* Note: StopIteration is already cleared by PyIter_Next() */ + if (PyErr_Occurred()) return NULL; - } if (PyList_Size(lz->saved) == 0) return NULL; it = PyObject_GetIter(lz->saved); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 16 00:16:26 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 15 Aug 2015 22:16:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_oddly_placed_whitespac?= =?utf-8?q?e?= Message-ID: <20150815221626.4925.93308@psf.io> https://hg.python.org/cpython/rev/77e621214488 changeset: 97396:77e621214488 user: Raymond Hettinger date: Sat Aug 15 15:16:12 2015 -0700 summary: Fix oddly placed whitespace files: Modules/itertoolsmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -963,7 +963,7 @@ */ return Py_BuildValue("O(O)(Oi)", Py_TYPE(lz), lz->it, lz->saved, lz->firstpass); - } +} static PyObject * cycle_setstate(cycleobject *lz, PyObject *state) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 16 02:24:30 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 16 Aug 2015 00:24:30 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_a_C-API_sect?= =?utf-8?q?ion=2E?= Message-ID: <20150816002430.15616.62132@psf.io> https://hg.python.org/peps/rev/b7f301a8eac7 changeset: 5954:b7f301a8eac7 user: Alexander Belopolsky date: Sat Aug 15 20:24:23 2015 -0400 summary: PEP 495: Added a C-API section. files: pep-0495.txt | 37 +++++++++++++++++++++++++++++++++++++ 1 files changed, 37 insertions(+), 0 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -103,6 +103,43 @@ ``first`` argument is not specified, the original value of the ``first`` attribute is copied to the result. +C-API +..... + +Access macros will be defined to extract the value of ``first`` from +``PyDateTime_DateTime`` and ``PyDateTime_Time`` objects. + +.. code:: + + bool PyDateTime_GET_FIRST(PyDateTime_DateTime *o) + +Return the value of ``first`` as a C99 ``bool``. + +.. code:: + + bool PyDateTime_TIME_GET_FIRST(PyDateTime_Time *o) + +Return the value of ``first`` as a C99 ``bool``. + +Additional constructors will be defined that will take an additional +boolean argument to specify the value of ``first`` in the created +instance: + +.. code:: + + PyObject* PyDateTime_FromDateAndTimeAndFirst(int year, int month, int day, int hour, int minute, int second, int usecond, bool first) + +Return a ``datetime.datetime`` object with the specified year, month, +day, hour, minute, second, microsecond and first. + +.. code:: + + PyObject* PyTime_FromTimeAndFirst(int hour, int minute, int second, int usecond, bool first) + +Return a ``datetime.time`` object with the specified hour, minute, +second, microsecond and first. + + Affected Behaviors ------------------ -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 16 05:19:07 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 16 Aug 2015 03:19:07 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Minor_markup_fix?= =?utf-8?q?=2E?= Message-ID: <20150816031907.21664.44153@psf.io> https://hg.python.org/peps/rev/1a8f5b53030e changeset: 5955:1a8f5b53030e user: Alexander Belopolsky date: Sat Aug 15 23:18:58 2015 -0400 summary: PEP 495: Minor markup fix. files: pep-0495.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -335,7 +335,7 @@ The value of "first" will be ignored in all operations except those that involve conversion between timezones. [#]_ As a consequence, -`datetime.datetime`` or ``datetime.time`` instances that differ only +``datetime.datetime`` or ``datetime.time`` instances that differ only by the value of ``first`` will compare as equal. Applications that need to differentiate between such instances should check the value of ``first`` or convert them to a timezone that does not have ambiguous -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 16 05:57:16 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 16 Aug 2015 03:57:16 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Corrected_the_miss?= =?utf-8?q?ing_time_rule_for_timestamp=2E?= Message-ID: <20150816035716.6312.47813@psf.io> https://hg.python.org/peps/rev/9da9a9224a13 changeset: 5956:9da9a9224a13 user: Alexander Belopolsky date: Sat Aug 15 23:57:08 2015 -0400 summary: PEP 495: Corrected the missing time rule for timestamp. files: pep-0495.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -198,7 +198,7 @@ The value returned by ``dt.timestamp()`` given a missing ``dt`` will be the larger of the two "nice to know" values -if ``dt.first == True`` and the larger otherwise. +if ``dt.first == True`` and the smaller otherwise. For example, on a system set to US/Eastern timezone:: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 16 17:42:21 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 16 Aug 2015 15:42:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324842=3A__Cross-r?= =?utf-8?q?eference_types=2ESimpleNamespace_from_the_namedtuple_docs?= Message-ID: <20150816153212.6332.73875@psf.io> https://hg.python.org/cpython/rev/678d93c273de changeset: 97397:678d93c273de user: Raymond Hettinger date: Sun Aug 16 08:32:01 2015 -0700 summary: Issue #24842: Cross-reference types.SimpleNamespace from the namedtuple docs files: Doc/library/collections.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -962,6 +962,9 @@ constructor that is convenient for use cases where named tuples are being subclassed. + * :meth:`types.SimpleNamespace` for a mutable namespace based on an underlying + dictionary instead of a tuple. + :class:`OrderedDict` objects ---------------------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 16 23:24:31 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 16 Aug 2015 21:24:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Inline_PyIter=5FNext=28=29?= =?utf-8?q?_matching_what_was_done_for_other_itertools=2E?= Message-ID: <20150816212429.47406.90447@psf.io> https://hg.python.org/cpython/rev/b9504ac1e7e8 changeset: 97398:b9504ac1e7e8 user: Raymond Hettinger date: Sun Aug 16 14:24:20 2015 -0700 summary: Inline PyIter_Next() matching what was done for other itertools. files: Modules/itertoolsmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1860,7 +1860,7 @@ return NULL; /* input not iterable */ } } - item = PyIter_Next(lz->active); + item = (*Py_TYPE(lz->active)->tp_iternext)(lz->active); if (item != NULL) return item; if (PyErr_Occurred()) { @@ -3434,7 +3434,7 @@ { PyObject *val, *oldtotal, *newtotal; - val = PyIter_Next(lz->it); + val = (*Py_TYPE(lz->it)->tp_iternext)(lz->it); if (val == NULL) return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 16 23:38:14 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 16 Aug 2015 21:38:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Neaten-up_whitespace=2C_ve?= =?utf-8?q?rtical_alignment=2C_and_line-wrapping=2E?= Message-ID: <20150816213814.13726.43427@psf.io> https://hg.python.org/cpython/rev/fba6ec3ef969 changeset: 97399:fba6ec3ef969 user: Raymond Hettinger date: Sun Aug 16 14:38:07 2015 -0700 summary: Neaten-up whitespace, vertical alignment, and line-wrapping. files: Modules/itertoolsmodule.c | 32 ++++++++++++++------------ 1 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -759,9 +759,9 @@ "Iterator wrapped to make it copyable"); static PyMethodDef tee_methods[] = { - {"__copy__", (PyCFunction)tee_copy, METH_NOARGS, teecopy_doc}, - {"__reduce__", (PyCFunction)tee_reduce, METH_NOARGS, reduce_doc}, - {"__setstate__", (PyCFunction)tee_setstate, METH_O, setstate_doc}, + {"__copy__", (PyCFunction)tee_copy, METH_NOARGS, teecopy_doc}, + {"__reduce__", (PyCFunction)tee_reduce, METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)tee_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -1407,7 +1407,8 @@ if (PyErr_Occurred()) PyErr_Clear(); PyErr_SetString(PyExc_ValueError, - "Stop argument for islice() must be None or an integer: 0 <= x <= sys.maxsize."); + "Stop argument for islice() must be None or " + "an integer: 0 <= x <= sys.maxsize."); return NULL; } } @@ -1422,14 +1423,16 @@ if (PyErr_Occurred()) PyErr_Clear(); PyErr_SetString(PyExc_ValueError, - "Stop argument for islice() must be None or an integer: 0 <= x <= sys.maxsize."); + "Stop argument for islice() must be None or " + "an integer: 0 <= x <= sys.maxsize."); return NULL; } } } if (start<0 || stop<-1) { PyErr_SetString(PyExc_ValueError, - "Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize."); + "Indices for islice() must be None or " + "an integer: 0 <= x <= sys.maxsize."); return NULL; } @@ -1845,19 +1848,19 @@ PyObject *item; if (lz->source == NULL) - return NULL; /* already stopped */ + return NULL; /* already stopped */ if (lz->active == NULL) { PyObject *iterable = PyIter_Next(lz->source); if (iterable == NULL) { Py_CLEAR(lz->source); - return NULL; /* no more input sources */ + return NULL; /* no more input sources */ } lz->active = PyObject_GetIter(iterable); Py_DECREF(iterable); if (lz->active == NULL) { Py_CLEAR(lz->source); - return NULL; /* input not iterable */ + return NULL; /* input not iterable */ } } item = (*Py_TYPE(lz->active)->tp_iternext)(lz->active); @@ -1867,10 +1870,10 @@ if (PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); else - return NULL; /* input raised an exception */ + return NULL; /* input raised an exception */ } Py_CLEAR(lz->active); - return chain_next(lz); /* recurse and use next active */ + return chain_next(lz); /* recurse and use next active */ } static PyObject * @@ -1928,7 +1931,7 @@ reduce_doc}, {"__setstate__", (PyCFunction)chain_setstate, METH_O, setstate_doc}, - {NULL, NULL} /* sentinel */ + {NULL, NULL} /* sentinel */ }; static PyTypeObject chain_type = { @@ -1980,7 +1983,7 @@ typedef struct { PyObject_HEAD - PyObject *pools; /* tuple of pool tuples */ + PyObject *pools; /* tuple of pool tuples */ Py_ssize_t *indices; /* one index per pool */ PyObject *result; /* most recently returned result tuple */ int stopped; /* set to 1 when the product iterator is exhausted */ @@ -3779,8 +3782,7 @@ ok = PyObject_IsTrue(item); } else { PyObject *good; - good = PyObject_CallFunctionObjArgs(lz->func, - item, NULL); + good = PyObject_CallFunctionObjArgs(lz->func, item, NULL); if (good == NULL) { Py_DECREF(item); return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 16 23:49:38 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 16 Aug 2015 21:49:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324874=3A_Speed-up?= =?utf-8?q?_itertools_and_make_it_pickles_more_compact=2E?= Message-ID: <20150816214938.21652.14776@psf.io> https://hg.python.org/cpython/rev/17b5c8ba6875 changeset: 97400:17b5c8ba6875 user: Raymond Hettinger date: Sun Aug 16 14:49:24 2015 -0700 summary: Issue #24874: Speed-up itertools and make it pickles more compact. files: Misc/NEWS | 3 + Modules/itertoolsmodule.c | 64 +++++++++++++++++--------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,9 @@ - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. +- Issue #24874: Improve speed of itertools.cycle() and make its + pickle more compact. + - Fix crash in itertools.cycle.__setstate__() when the first argument wasn't a list. diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1,3 +1,5 @@ + +#define PY_SSIZE_T_CLEAN #include "Python.h" #include "structmember.h" @@ -863,6 +865,7 @@ PyObject_HEAD PyObject *it; PyObject *saved; + Py_ssize_t index; int firstpass; } cycleobject; @@ -902,6 +905,7 @@ } lz->it = it; lz->saved = saved; + lz->index = 0; lz->firstpass = 0; return (PyObject *)lz; @@ -911,15 +915,16 @@ cycle_dealloc(cycleobject *lz) { PyObject_GC_UnTrack(lz); + Py_XDECREF(lz->it); Py_XDECREF(lz->saved); - Py_XDECREF(lz->it); Py_TYPE(lz)->tp_free(lz); } static int cycle_traverse(cycleobject *lz, visitproc visit, void *arg) { - Py_VISIT(lz->it); + if (lz->it) + Py_VISIT(lz->it); Py_VISIT(lz->saved); return 0; } @@ -928,13 +933,13 @@ cycle_next(cycleobject *lz) { PyObject *item; - PyObject *it; - PyObject *tmp; - - while (1) { + + if (lz->it != NULL) { item = PyIter_Next(lz->it); if (item != NULL) { - if (!lz->firstpass && PyList_Append(lz->saved, item)) { + if (lz->firstpass) + return item; + if (PyList_Append(lz->saved, item)) { Py_DECREF(item); return NULL; } @@ -942,27 +947,41 @@ } /* Note: StopIteration is already cleared by PyIter_Next() */ if (PyErr_Occurred()) - return NULL; - if (PyList_Size(lz->saved) == 0) return NULL; - it = PyObject_GetIter(lz->saved); - if (it == NULL) - return NULL; - tmp = lz->it; - lz->it = it; - lz->firstpass = 1; - Py_DECREF(tmp); + Py_CLEAR(lz->it); } + if (Py_SIZE(lz->saved) == 0) + return NULL; + item = PyList_GET_ITEM(lz->saved, lz->index); + lz->index++; + if (lz->index >= Py_SIZE(lz->saved)) + lz->index = 0; + Py_INCREF(item); + return item; } static PyObject * cycle_reduce(cycleobject *lz) { - /* Create a new cycle with the iterator tuple, then set - * the saved state on it. - */ - return Py_BuildValue("O(O)(Oi)", Py_TYPE(lz), - lz->it, lz->saved, lz->firstpass); + /* Create a new cycle with the iterator tuple, then set the saved state */ + if (lz->it == NULL) { + PyObject *it = PyObject_GetIter(lz->saved); + if (it == NULL) + return NULL; + if (lz->index != 0) { + _Py_IDENTIFIER(__setstate__); + PyObject *res = _PyObject_CallMethodId(it, &PyId___setstate__, + "n", lz->index); + if (res == NULL) { + Py_DECREF(it); + return NULL; + } + Py_DECREF(res); + } + return Py_BuildValue("O(N)(Oi)", Py_TYPE(lz), it, lz->saved, 1); + } + return Py_BuildValue("O(O)(Oi)", Py_TYPE(lz), lz->it, lz->saved, + lz->firstpass); } static PyObject * @@ -972,10 +991,11 @@ int firstpass; if (!PyArg_ParseTuple(state, "O!i", &PyList_Type, &saved, &firstpass)) return NULL; + Py_INCREF(saved); Py_CLEAR(lz->saved); lz->saved = saved; - Py_XINCREF(lz->saved); lz->firstpass = firstpass != 0; + lz->index = 0; Py_RETURN_NONE; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 02:10:21 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 17 Aug 2015 00:10:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_error_information_to_a?= =?utf-8?q?_failing_test_to_help_diagnose_a_buildbot_failure=2E?= Message-ID: <20150817001015.91831.28091@psf.io> https://hg.python.org/cpython/rev/f41ac4368e65 changeset: 97401:f41ac4368e65 user: Raymond Hettinger date: Sun Aug 16 17:08:48 2015 -0700 summary: Add error information to a failing test to help diagnose a buildbot failure. files: Lib/test/test_symbol.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_symbol.py b/Lib/test/test_symbol.py --- a/Lib/test/test_symbol.py +++ b/Lib/test/test_symbol.py @@ -38,7 +38,10 @@ self.assertFalse(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) self.assertEqual((0, b''), self._generate_symbols(GRAMMAR_FILE, TEST_PY_FILE)) - self.assertTrue(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE)) + self.assertTrue(filecmp.cmp(SYMBOL_FILE, TEST_PY_FILE), + 'symbol stat: %r\ntest_py stat: %r\n' % + (os.stat(SYMBOL_FILE), + os.stat(TEST_PY_FILE))) if __name__ == "__main__": -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 02:20:14 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 17 Aug 2015 00:20:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324774=3A_Fix_docstring_in_http=2Eserver=2Etest=2E?= Message-ID: <20150817002005.91819.62760@psf.io> https://hg.python.org/cpython/rev/845c79097c21 changeset: 97403:845c79097c21 branch: 3.5 parent: 97391:70d422efa742 parent: 97402:d9e0c82d8653 user: Robert Collins date: Mon Aug 17 12:19:19 2015 +1200 summary: Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. files: Lib/http/server.py | 3 +-- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -1167,8 +1167,7 @@ ServerClass=HTTPServer, protocol="HTTP/1.0", port=8000, bind=""): """Test the HTTP request handler class. - This runs an HTTP server on port 8000 (or the first command line - argument). + This runs an HTTP server on port 8000 (or the port argument). """ server_address = (bind, port) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -622,6 +622,7 @@ Brad Howes Mike Hoy Ben Hoyt +Chiu-Hsiang Hsu Chih-Hao Huang Christian Hudon Lawrence Hudson diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,8 @@ Library ------- +- Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. + - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 02:20:15 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 17 Aug 2015 00:20:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324774=3A_Fix_docstring_in_http=2Eserver=2Etest?= =?utf-8?q?=2E?= Message-ID: <20150817002005.91823.18714@psf.io> https://hg.python.org/cpython/rev/a8de693ebe66 changeset: 97404:a8de693ebe66 parent: 97401:f41ac4368e65 parent: 97403:845c79097c21 user: Robert Collins date: Mon Aug 17 12:19:35 2015 +1200 summary: Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. files: Lib/http/server.py | 3 +-- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -1167,8 +1167,7 @@ ServerClass=HTTPServer, protocol="HTTP/1.0", port=8000, bind=""): """Test the HTTP request handler class. - This runs an HTTP server on port 8000 (or the first command line - argument). + This runs an HTTP server on port 8000 (or the port argument). """ server_address = (bind, port) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -622,6 +622,7 @@ Brad Howes Mike Hoy Ben Hoyt +Chiu-Hsiang Hsu Chih-Hao Huang Christian Hudon Lawrence Hudson diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Library ------- +- Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. + - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 02:20:15 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 17 Aug 2015 00:20:15 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Nzc0?= =?utf-8?q?=3A_Fix_docstring_in_http=2Eserver=2Etest=2E?= Message-ID: <20150817002004.36757.16126@psf.io> https://hg.python.org/cpython/rev/d9e0c82d8653 changeset: 97402:d9e0c82d8653 branch: 3.4 parent: 97386:cce226356477 user: Robert Collins date: Mon Aug 17 12:18:35 2015 +1200 summary: Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. files: Lib/http/server.py | 3 +-- Misc/ACKS | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -1211,8 +1211,7 @@ ServerClass=HTTPServer, protocol="HTTP/1.0", port=8000, bind=""): """Test the HTTP request handler class. - This runs an HTTP server on port 8000 (or the first command line - argument). + This runs an HTTP server on port 8000 (or the port argument). """ server_address = (bind, port) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -610,6 +610,7 @@ Ken Howard Brad Howes Mike Hoy +Chiu-Hsiang Hsu Chih-Hao Huang Christian Hudon Lawrence Hudson diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -75,6 +75,8 @@ Library ------- +- Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. + - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 03:55:50 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 01:55:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150817015549.6782.53400@psf.io> https://hg.python.org/cpython/rev/8e40c55efcbc changeset: 97408:8e40c55efcbc parent: 97404:a8de693ebe66 parent: 97407:3057a9d76d5d user: Terry Jan Reedy date: Sun Aug 16 21:55:13 2015 -0400 summary: Merge with 3.5 files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1183,6 +1183,7 @@ Wes Rishel Daniel Riti Juan M. Bello Rivas +Mohd Sanad Zaki Rizvi Davide Rizzo Anthony Roach Carl Robben -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 03:55:49 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 01:55:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNjcy?= =?utf-8?q?=3A_ACKS?= Message-ID: <20150817015549.4917.44571@psf.io> https://hg.python.org/cpython/rev/c1031eb12aa1 changeset: 97406:c1031eb12aa1 branch: 3.4 parent: 97402:d9e0c82d8653 user: Terry Jan Reedy date: Sun Aug 16 21:54:39 2015 -0400 summary: Issue #23672: ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1152,6 +1152,7 @@ Wes Rishel Daniel Riti Juan M. Bello Rivas +Mohd Sanad Zaki Rizvi Davide Rizzo Anthony Roach Carl Robben -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 03:55:51 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 01:55:51 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150817015549.91807.15684@psf.io> https://hg.python.org/cpython/rev/3057a9d76d5d changeset: 97407:3057a9d76d5d branch: 3.5 parent: 97403:845c79097c21 parent: 97406:c1031eb12aa1 user: Terry Jan Reedy date: Sun Aug 16 21:54:58 2015 -0400 summary: Merge with 3.4 files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1183,6 +1183,7 @@ Wes Rishel Daniel Riti Juan M. Bello Rivas +Mohd Sanad Zaki Rizvi Davide Rizzo Anthony Roach Carl Robben -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 03:55:50 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 01:55:50 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNjcy?= =?utf-8?q?=3A_ACKS?= Message-ID: <20150817015549.91835.39676@psf.io> https://hg.python.org/cpython/rev/d54aa163e4ec changeset: 97405:d54aa163e4ec branch: 2.7 parent: 97385:724d9b589cfc user: Terry Jan Reedy date: Sun Aug 16 21:54:35 2015 -0400 summary: Issue #23672: ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1139,6 +1139,7 @@ Wes Rishel Daniel Riti Juan M. Bello Rivas +Mohd Sanad Zaki Rizvi Davide Rizzo Anthony Roach Carl Robben -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 04:12:06 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 02:12:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Idle_NEWS_entr?= =?utf-8?q?ies=2E?= Message-ID: <20150817021204.91807.87022@psf.io> https://hg.python.org/cpython/rev/c31b58b31e29 changeset: 97409:c31b58b31e29 branch: 2.7 parent: 97405:d54aa163e4ec user: Terry Jan Reedy date: Sun Aug 16 22:11:43 2015 -0400 summary: Idle NEWS entries. files: Misc/NEWS | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -141,6 +141,19 @@ IDLE ---- +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + - Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for decoding unicode literals. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 04:15:35 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 02:15:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Idle_NEWS_entr?= =?utf-8?q?ies=2E?= Message-ID: <20150817021535.21662.39065@psf.io> https://hg.python.org/cpython/rev/b88d16fdf8b2 changeset: 97410:b88d16fdf8b2 branch: 3.4 parent: 97406:c1031eb12aa1 user: Terry Jan Reedy date: Sun Aug 16 22:12:36 2015 -0400 summary: Idle NEWS entries. files: Misc/NEWS | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -391,6 +391,19 @@ IDLE ---- +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + - Issue #23184: remove unused names and imports in idlelib. Initial patch by Al Sweigart. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 04:15:35 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 02:15:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Idle_NEWS_entries=2E?= Message-ID: <20150817021535.33543.10350@psf.io> https://hg.python.org/cpython/rev/abb0899dc6f6 changeset: 97411:abb0899dc6f6 branch: 3.5 parent: 97407:3057a9d76d5d parent: 97410:b88d16fdf8b2 user: Terry Jan Reedy date: Sun Aug 16 22:14:05 2015 -0400 summary: Idle NEWS entries. files: Misc/NEWS | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -92,6 +92,22 @@ - Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. +IDLE +---- + +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 04:15:36 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 02:15:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Idle_NEWS_entries=2E?= Message-ID: <20150817021535.47414.79747@psf.io> https://hg.python.org/cpython/rev/d43b2efdc3bf changeset: 97412:d43b2efdc3bf parent: 97408:8e40c55efcbc parent: 97411:abb0899dc6f6 user: Terry Jan Reedy date: Sun Aug 16 22:15:09 2015 -0400 summary: Idle NEWS entries. files: Misc/NEWS | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -97,6 +97,22 @@ - Issue #24867: Fix Task.get_stack() for 'async def' coroutines +IDLE +---- + +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 04:45:03 2015 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 17 Aug 2015 02:45:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324379=3A_Add_oper?= =?utf-8?q?ator=2Esubscript=28=29_as_a_convenience_for_building_slices=2E?= Message-ID: <20150817024501.47414.67260@psf.io> https://hg.python.org/cpython/rev/dccc4e63aef5 changeset: 97413:dccc4e63aef5 user: Raymond Hettinger date: Sun Aug 16 19:43:34 2015 -0700 summary: Issue #24379: Add operator.subscript() as a convenience for building slices. files: Doc/library/operator.rst | 15 ++++++++++++ Doc/whatsnew/3.6.rst | 7 ++++- Lib/operator.py | 28 ++++++++++++++++++++++- Lib/test/test_operator.py | 33 +++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -333,6 +333,21 @@ [('orange', 1), ('banana', 2), ('apple', 3), ('pear', 5)] +.. data:: subscript + + A helper to turn subscript notation into indexing objects. This can be + used to create item access patterns ahead of time to pass them into + various subscriptable objects. + + For example: + + * ``subscript[5] == 5`` + * ``subscript[3:7:2] == slice(3, 7, 2)`` + * ``subscript[5, 8] == (5, 8)`` + + .. versionadded:: 3.6 + + .. function:: methodcaller(name[, args...]) Return a callable object that calls the method *name* on its operand. If diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -95,7 +95,12 @@ Improved Modules ================ -* None yet. +operator +-------- + +* New object :data:`operator.subscript` makes it easier to create complex + indexers. For example: ``subscript[0:10:2] == slice(0, 10, 2)`` + (Contributed by Joe Jevnik in :issue:`24379`.) Optimizations diff --git a/Lib/operator.py b/Lib/operator.py --- a/Lib/operator.py +++ b/Lib/operator.py @@ -17,7 +17,7 @@ 'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le', 'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod', 'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', - 'setitem', 'sub', 'truediv', 'truth', 'xor'] + 'setitem', 'sub', 'subscript', 'truediv', 'truth', 'xor'] from builtins import abs as _abs @@ -408,6 +408,32 @@ return a + at object.__new__ # create a singleton instance +class subscript: + """ + A helper to turn subscript notation into indexing objects. This can be + used to create item access patterns ahead of time to pass them into + various subscriptable objects. + + For example: + subscript[5] == 5 + subscript[3:7:2] == slice(3, 7, 2) + subscript[5, 8] == (5, 8) + """ + __slots__ = () + + def __new__(cls): + raise TypeError("cannot create '{}' instances".format(cls.__name__)) + + @staticmethod + def __getitem__(key): + return key + + @staticmethod + def __reduce__(): + return 'subscript' + + try: from _operator import * except ImportError: diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -596,5 +596,38 @@ module2 = c_operator +class SubscriptTestCase: + def test_subscript(self): + subscript = self.module.subscript + self.assertIsNone(subscript[None]) + self.assertEqual(subscript[0], 0) + self.assertEqual(subscript[0:1:2], slice(0, 1, 2)) + self.assertEqual( + subscript[0, ..., :2, ...], + (0, Ellipsis, slice(2), Ellipsis), + ) + + def test_pickle(self): + from operator import subscript + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + self.assertIs( + pickle.loads(pickle.dumps(subscript, proto)), + subscript, + ) + + def test_singleton(self): + with self.assertRaises(TypeError): + type(self.module.subscript)() + + def test_immutable(self): + with self.assertRaises(AttributeError): + self.module.subscript.attr = None + + +class PySubscriptTestCase(SubscriptTestCase, PyOperatorTestCase): + pass + + if __name__ == "__main__": unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 05:22:48 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 03:22:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Entries_for_id?= =?utf-8?q?lelib/NEWS=2Etxt?= Message-ID: <20150817032244.6806.84959@psf.io> https://hg.python.org/cpython/rev/4884af6d3e30 changeset: 97414:4884af6d3e30 branch: 2.7 parent: 97409:c31b58b31e29 user: Terry Jan Reedy date: Sun Aug 16 23:22:32 2015 -0400 summary: Entries for idlelib/NEWS.txt files: Lib/idlelib/NEWS.txt | 26 ++++++++++++++++++++++++-- 1 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,7 +1,29 @@ +What's New in IDLE 2.7.11? +========================= + +*Release date: + +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + +- Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for + decoding unicode literals. + + What's New in IDLE 2.7.10? ========================= -*Release data: 2015-05-23* +*Release date: 2015-05-23* - Issue #23583: Fixed writing unicode to standard output stream in IDLE. @@ -20,7 +42,7 @@ What's New in IDLE 2.7.9? ========================= -*Release data: 2014-12-10* +*Release date: 2014-12-10* - Issue #16893: Update Idle doc chapter to match current Idle and add new information. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 05:24:44 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 03:24:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Entries_for_id?= =?utf-8?q?lelib/NEWS=2Etxt?= Message-ID: <20150817032444.6316.54742@psf.io> https://hg.python.org/cpython/rev/e3b79f8dcf53 changeset: 97415:e3b79f8dcf53 branch: 3.4 parent: 97410:b88d16fdf8b2 user: Terry Jan Reedy date: Sun Aug 16 23:23:16 2015 -0400 summary: Entries for idlelib/NEWS.txt files: Lib/idlelib/NEWS.txt | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,7 +1,20 @@ -What's New in Idle 3.4.3? +What's New in Idle 3.4.4? ========================= *Release date: 2015-??-??* +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + - Issue #23184: remove unused names and imports in idlelib. Initial patch by Al Sweigart. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 05:24:44 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 03:24:44 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Entries_for_idlelib/NEWS=2Etxt?= Message-ID: <20150817032444.15605.82339@psf.io> https://hg.python.org/cpython/rev/41d47fe9375f changeset: 97416:41d47fe9375f branch: 3.5 parent: 97411:abb0899dc6f6 parent: 97415:e3b79f8dcf53 user: Terry Jan Reedy date: Sun Aug 16 23:24:11 2015 -0400 summary: Entries for idlelib/NEWS.txt files: Lib/idlelib/NEWS.txt | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -2,6 +2,19 @@ ========================= *Release date: 2015-09-13* ?? +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + - Issue #23184: remove unused names and imports in idlelib. Initial patch by Al Sweigart. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 05:24:44 2015 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Aug 2015 03:24:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5_Entries_for_idlelib/NEWS=2Etxt?= Message-ID: <20150817032444.15627.29102@psf.io> https://hg.python.org/cpython/rev/04dfdde6eb18 changeset: 97417:04dfdde6eb18 parent: 97413:dccc4e63aef5 parent: 97416:41d47fe9375f user: Terry Jan Reedy date: Sun Aug 16 23:24:32 2015 -0400 summary: Merge with 3.5 Entries for idlelib/NEWS.txt files: Lib/idlelib/NEWS.txt | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -2,6 +2,19 @@ ========================= *Release date: 2015-09-13* ?? +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + - Issue #23184: remove unused names and imports in idlelib. Initial patch by Al Sweigart. -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Mon Aug 17 10:15:54 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Mon, 17 Aug 2015 08:15:54 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-17 Message-ID: Results for project python_default-nightly, build date 2015-08-17 09:02:37 commit: 04dfdde6eb18692ef13327a284bbbe1a5fbc5cc2 revision date: 2015-08-17 06:24:32 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec 0.11152% -2.29176% :-( regex_v8 sec 0.04744% -3.47810% :-| nbody sec 0.23181% -0.94705% :-| json_dump_v2 sec 0.59619% -0.80930% :-| normal_startup sec -0.21423% -0.05082% Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Mon Aug 17 19:02:59 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 17 Aug 2015 17:02:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogZG9jczogRml4IGlu?= =?utf-8?q?spect_docs_re_gi=5Fyieldfrom?= Message-ID: <20150817170257.4935.17495@psf.io> https://hg.python.org/cpython/rev/caa2d561e9dc changeset: 97418:caa2d561e9dc branch: 3.5 parent: 97416:41d47fe9375f user: Yury Selivanov date: Mon Aug 17 13:02:42 2015 -0400 summary: docs: Fix inspect docs re gi_yieldfrom files: Doc/library/inspect.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -178,6 +178,10 @@ +-----------+-----------------+---------------------------+ | | gi_code | code | +-----------+-----------------+---------------------------+ +| | gi_yieldfrom | object being iterated by | +| | | ``yield from``, or | +| | | ``None`` | ++-----------+-----------------+---------------------------+ | coroutine | __name__ | name | +-----------+-----------------+---------------------------+ | | __qualname__ | qualified name | @@ -191,10 +195,6 @@ +-----------+-----------------+---------------------------+ | | cr_code | code | +-----------+-----------------+---------------------------+ -| | gi_yieldfrom | object being iterated by | -| | | ``yield from``, or | -| | | ``None`` | -+-----------+-----------------+---------------------------+ | builtin | __doc__ | documentation string | +-----------+-----------------+---------------------------+ | | __name__ | original name of this | -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 19:04:53 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 17 Aug 2015 17:04:53 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogZG9jczogQ2xhcmlm?= =?utf-8?q?y_that_gi=5Fyieldfrom_was_first_added_in_3=2E5?= Message-ID: <20150817170453.6316.15903@psf.io> https://hg.python.org/cpython/rev/948d8ea8e7a6 changeset: 97420:948d8ea8e7a6 branch: 3.5 parent: 97418:caa2d561e9dc user: Yury Selivanov date: Mon Aug 17 13:04:41 2015 -0400 summary: docs: Clarify that gi_yieldfrom was first added in 3.5 files: Doc/library/inspect.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -209,9 +209,10 @@ .. versionchanged:: 3.5 - Add ``__qualname__`` attribute to generators. The ``__name__`` attribute of - generators is now set from the function name, instead of the code name, and - it can now be modified. + Add ``__qualname__`` and ``gi_yieldfrom`` attributes to generators. + + The ``__name__`` attribute of generators is now set from the function + name, instead of the code name, and it can now be modified. .. function:: getmembers(object[, predicate]) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 19:04:53 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 17 Aug 2015 17:04:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150817170453.6302.27135@psf.io> https://hg.python.org/cpython/rev/cc093f3037bd changeset: 97421:cc093f3037bd parent: 97419:4610368e558a parent: 97420:948d8ea8e7a6 user: Yury Selivanov date: Mon Aug 17 13:04:49 2015 -0400 summary: Merge 3.5 files: Doc/library/inspect.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -209,9 +209,10 @@ .. versionchanged:: 3.5 - Add ``__qualname__`` attribute to generators. The ``__name__`` attribute of - generators is now set from the function name, instead of the code name, and - it can now be modified. + Add ``__qualname__`` and ``gi_yieldfrom`` attributes to generators. + + The ``__name__`` attribute of generators is now set from the function + name, instead of the code name, and it can now be modified. .. function:: getmembers(object[, predicate]) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 17 19:15:40 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 17 Aug 2015 17:15:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150817170257.33401.77399@psf.io> https://hg.python.org/cpython/rev/4610368e558a changeset: 97419:4610368e558a parent: 97417:04dfdde6eb18 parent: 97418:caa2d561e9dc user: Yury Selivanov date: Mon Aug 17 13:02:53 2015 -0400 summary: Merge 3.5 files: Doc/library/inspect.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -178,6 +178,10 @@ +-----------+-----------------+---------------------------+ | | gi_code | code | +-----------+-----------------+---------------------------+ +| | gi_yieldfrom | object being iterated by | +| | | ``yield from``, or | +| | | ``None`` | ++-----------+-----------------+---------------------------+ | coroutine | __name__ | name | +-----------+-----------------+---------------------------+ | | __qualname__ | qualified name | @@ -191,10 +195,6 @@ +-----------+-----------------+---------------------------+ | | cr_code | code | +-----------+-----------------+---------------------------+ -| | gi_yieldfrom | object being iterated by | -| | | ``yield from``, or | -| | | ``None`` | -+-----------+-----------------+---------------------------+ | builtin | __doc__ | documentation string | +-----------+-----------------+---------------------------+ | | __name__ | original name of this | -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 04:16:45 2015 From: python-checkins at python.org (ned.deily) Date: Tue, 18 Aug 2015 02:16:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324079=3A_merge_from_3=2E4?= Message-ID: <20150818021645.13724.17326@psf.io> https://hg.python.org/cpython/rev/17ce3486fd8f changeset: 97424:17ce3486fd8f branch: 3.5 parent: 97420:948d8ea8e7a6 parent: 97423:ad0491f85050 user: Ned Deily date: Mon Aug 17 22:11:57 2015 -0400 summary: Issue #24079: merge from 3.4 files: Doc/library/xml.etree.elementtree.rst | 30 +++++++++----- 1 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -651,21 +651,29 @@ .. attribute:: text + tail - The *text* attribute can be used to hold additional data associated with - the element. As the name implies this attribute is usually a string but - may be any application-specific object. If the element is created from - an XML file the attribute will contain any text found between the element - tags. + These attributes can be used to hold additional data associated with + the element. Their values are usually strings but may be any + application-specific object. If the element is created from + an XML file, the *text* attribute holds either the text between + the element's start tag and its first child or end tag, or ``None``, and + the *tail* attribute holds either the text between the element's + end tag and the next tag, or ``None``. For the XML data + .. code-block:: xml - .. attribute:: tail + 1234 - The *tail* attribute can be used to hold additional data associated with - the element. This attribute is usually a string but may be any - application-specific object. If the element is created from an XML file - the attribute will contain any text found after the element's end tag and - before the next tag. + the *a* element has ``None`` for both *text* and *tail* attributes, + the *b* element has *text* ``"1"`` and *tail* ``"4"``, + the *c* element has *text* ``"2"`` and *tail* ``None``, + and the *d* element has *text* ``None`` and *tail* ``"3"``. + + To collect the inner text of an element, see :meth:`itertext`, for + example ``"".join(element.itertext())``. + + Applications may store arbitrary objects in these attributes. .. attribute:: attrib -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 04:17:08 2015 From: python-checkins at python.org (ned.deily) Date: Tue, 18 Aug 2015 02:17:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDc5?= =?utf-8?q?=3A_Improve_description_of_the_text_and_tail_attributes_for?= Message-ID: <20150818021645.91817.96008@psf.io> https://hg.python.org/cpython/rev/ad0491f85050 changeset: 97423:ad0491f85050 branch: 3.4 parent: 97415:e3b79f8dcf53 user: Ned Deily date: Mon Aug 17 22:11:17 2015 -0400 summary: Issue #24079: Improve description of the text and tail attributes for ElementTree Element objects. Initial patch by Martin Panter. files: Doc/library/xml.etree.elementtree.rst | 30 +++++++++----- 1 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -651,21 +651,29 @@ .. attribute:: text + tail - The *text* attribute can be used to hold additional data associated with - the element. As the name implies this attribute is usually a string but - may be any application-specific object. If the element is created from - an XML file the attribute will contain any text found between the element - tags. + These attributes can be used to hold additional data associated with + the element. Their values are usually strings but may be any + application-specific object. If the element is created from + an XML file, the *text* attribute holds either the text between + the element's start tag and its first child or end tag, or ``None``, and + the *tail* attribute holds either the text between the element's + end tag and the next tag, or ``None``. For the XML data + .. code-block:: xml - .. attribute:: tail + 1234 - The *tail* attribute can be used to hold additional data associated with - the element. This attribute is usually a string but may be any - application-specific object. If the element is created from an XML file - the attribute will contain any text found after the element's end tag and - before the next tag. + the *a* element has ``None`` for both *text* and *tail* attributes, + the *b* element has *text* ``"1"`` and *tail* ``"4"``, + the *c* element has *text* ``"2"`` and *tail* ``None``, + and the *d* element has *text* ``None`` and *tail* ``"3"``. + + To collect the inner text of an element, see :meth:`itertext`, for + example ``"".join(element.itertext())``. + + Applications may store arbitrary objects in these attributes. .. attribute:: attrib -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 04:17:08 2015 From: python-checkins at python.org (ned.deily) Date: Tue, 18 Aug 2015 02:17:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0MDc5?= =?utf-8?q?=3A_Improve_description_of_the_text_and_tail_attributes_for?= Message-ID: <20150818021644.33140.88@psf.io> https://hg.python.org/cpython/rev/d3cda8cf4d42 changeset: 97422:d3cda8cf4d42 branch: 2.7 parent: 97414:4884af6d3e30 user: Ned Deily date: Mon Aug 17 22:10:47 2015 -0400 summary: Issue #24079: Improve description of the text and tail attributes for ElementTree Element objects. Initial patch by Martin Panter. files: Doc/library/xml.etree.elementtree.rst | 30 +++++++++----- 1 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -600,21 +600,29 @@ .. attribute:: text + tail - The *text* attribute can be used to hold additional data associated with - the element. As the name implies this attribute is usually a string but - may be any application-specific object. If the element is created from - an XML file the attribute will contain any text found between the element - tags. + These attributes can be used to hold additional data associated with + the element. Their values are usually strings but may be any + application-specific object. If the element is created from + an XML file, the *text* attribute holds either the text between + the element's start tag and its first child or end tag, or ``None``, and + the *tail* attribute holds either the text between the element's + end tag and the next tag, or ``None``. For the XML data + .. code-block:: xml - .. attribute:: tail + 1234 - The *tail* attribute can be used to hold additional data associated with - the element. This attribute is usually a string but may be any - application-specific object. If the element is created from an XML file - the attribute will contain any text found after the element's end tag and - before the next tag. + the *a* element has ``None`` for both *text* and *tail* attributes, + the *b* element has *text* ``"1"`` and *tail* ``"4"``, + the *c* element has *text* ``"2"`` and *tail* ``None``, + and the *d* element has *text* ``None`` and *tail* ``"3"``. + + To collect the inner text of an element, see :meth:`itertext`, for + example ``"".join(element.itertext())``. + + Applications may store arbitrary objects in these attributes. .. attribute:: attrib -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 04:17:28 2015 From: python-checkins at python.org (ned.deily) Date: Tue, 18 Aug 2015 02:17:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324079=3A_merge_from_3=2E5?= Message-ID: <20150818021645.36755.55971@psf.io> https://hg.python.org/cpython/rev/3c94ece57c43 changeset: 97425:3c94ece57c43 parent: 97421:cc093f3037bd parent: 97424:17ce3486fd8f user: Ned Deily date: Mon Aug 17 22:15:54 2015 -0400 summary: Issue #24079: merge from 3.5 files: Doc/library/xml.etree.elementtree.rst | 30 +++++++++----- 1 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -651,21 +651,29 @@ .. attribute:: text + tail - The *text* attribute can be used to hold additional data associated with - the element. As the name implies this attribute is usually a string but - may be any application-specific object. If the element is created from - an XML file the attribute will contain any text found between the element - tags. + These attributes can be used to hold additional data associated with + the element. Their values are usually strings but may be any + application-specific object. If the element is created from + an XML file, the *text* attribute holds either the text between + the element's start tag and its first child or end tag, or ``None``, and + the *tail* attribute holds either the text between the element's + end tag and the next tag, or ``None``. For the XML data + .. code-block:: xml - .. attribute:: tail + 1234 - The *tail* attribute can be used to hold additional data associated with - the element. This attribute is usually a string but may be any - application-specific object. If the element is created from an XML file - the attribute will contain any text found after the element's end tag and - before the next tag. + the *a* element has ``None`` for both *text* and *tail* attributes, + the *b* element has *text* ``"1"`` and *tail* ``"4"``, + the *c* element has *text* ``"2"`` and *tail* ``None``, + and the *d* element has *text* ``None`` and *tail* ``"3"``. + + To collect the inner text of an element, see :meth:`itertext`, for + example ``"".join(element.itertext())``. + + Applications may store arbitrary objects in these attributes. .. attribute:: attrib -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 06:00:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 04:00:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150818034400.15623.6032@psf.io> https://hg.python.org/cpython/rev/a8715361180e changeset: 97427:a8715361180e parent: 97425:3c94ece57c43 parent: 97426:637a9d6328f6 user: Yury Selivanov date: Mon Aug 17 23:43:54 2015 -0400 summary: Merge 3.5 files: Doc/library/os.path.rst | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -82,8 +82,21 @@ Return the longest path prefix (taken character-by-character) that is a prefix of all paths in *list*. If *list* is empty, return the empty string - (``''``). Note that this may return invalid paths because it works a - character at a time. To obtain a valid path, see :func:`commonpath`. + (``''``). + + .. note:: + + This function may return invalid paths because it works a + character at a time. To obtain a valid path, see + :func:`commonpath`. + + :: + + >>> os.path.commonprefix(['/dir1/dir2', '/dir3/dir4']) + '/dir' + + >>> os.path.commonpath(['/dir1/dir2', '/dir3/dir4']) + '/' .. function:: dirname(path) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 06:00:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 04:00:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogZG9jczogSW1wcm92?= =?utf-8?q?e_docs_for_os=2Epath=2Ecommonprefix?= Message-ID: <20150818034400.6320.19991@psf.io> https://hg.python.org/cpython/rev/637a9d6328f6 changeset: 97426:637a9d6328f6 branch: 3.5 parent: 97424:17ce3486fd8f user: Yury Selivanov date: Mon Aug 17 23:43:43 2015 -0400 summary: docs: Improve docs for os.path.commonprefix files: Doc/library/os.path.rst | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -82,8 +82,21 @@ Return the longest path prefix (taken character-by-character) that is a prefix of all paths in *list*. If *list* is empty, return the empty string - (``''``). Note that this may return invalid paths because it works a - character at a time. To obtain a valid path, see :func:`commonpath`. + (``''``). + + .. note:: + + This function may return invalid paths because it works a + character at a time. To obtain a valid path, see + :func:`commonpath`. + + :: + + >>> os.path.commonprefix(['/dir1/dir2', '/dir3/dir4']) + '/dir' + + >>> os.path.commonpath(['/dir1/dir2', '/dir3/dir4']) + '/' .. function:: dirname(path) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 07:05:08 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 18 Aug 2015 05:05:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324878=3A__Add_doc?= =?utf-8?q?strings_to_selected_namedtuples?= Message-ID: <20150818050451.33302.8024@psf.io> https://hg.python.org/cpython/rev/40f2bbb922e6 changeset: 97428:40f2bbb922e6 user: Raymond Hettinger date: Mon Aug 17 22:04:45 2015 -0700 summary: Issue #24878: Add docstrings to selected namedtuples files: Lib/aifc.py | 8 ++++++++ Lib/dis.py | 9 +++++++++ Lib/sched.py | 11 +++++++++++ Lib/selectors.py | 12 ++++++++++-- Lib/shutil.py | 3 +++ Lib/sndhdr.py | 12 ++++++++++++ 6 files changed, 53 insertions(+), 2 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -257,6 +257,14 @@ _aifc_params = namedtuple('_aifc_params', 'nchannels sampwidth framerate nframes comptype compname') +_aifc_params.nchannels.__doc__ = 'Number of audio channels (1 for mono, 2 for stereo)' +_aifc_params.sampwidth.__doc__ = 'Ample width in bytes' +_aifc_params.framerate.__doc__ = 'Sampling frequency' +_aifc_params.nframes.__doc__ = 'Number of audio frames' +_aifc_params.comptype.__doc__ = 'Compression type ("NONE" for AIFF files)' +_aifc_params.compname.__doc__ = ("""A human-readable version ofcompression type +('not compressed' for AIFF files)'""") + class Aifc_read: # Variables used in this class: diff --git a/Lib/dis.py b/Lib/dis.py --- a/Lib/dis.py +++ b/Lib/dis.py @@ -162,6 +162,15 @@ _Instruction = collections.namedtuple("_Instruction", "opname opcode arg argval argrepr offset starts_line is_jump_target") +_Instruction.opname.__doc__ = "Human readable name for operation" +_Instruction.opcode.__doc__ = "Numeric code for operation" +_Instruction.arg.__doc__ = "Numeric argument to operation (if any), otherwise None" +_Instruction.argval.__doc__ = "Resolved arg value (if known), otherwise same as arg" +_Instruction.argrepr.__doc__ = "Human readable description of operation argument" +_Instruction.offset.__doc__ = "Start index of operation within bytecode sequence" +_Instruction.starts_line.__doc__ = "Line started by this opcode (if any), otherwise None" +_Instruction.is_jump_target.__doc__ = "True if other code jumps to here, otherwise False" + class Instruction(_Instruction): """Details for a bytecode operation diff --git a/Lib/sched.py b/Lib/sched.py --- a/Lib/sched.py +++ b/Lib/sched.py @@ -46,6 +46,17 @@ def __gt__(s, o): return (s.time, s.priority) > (o.time, o.priority) def __ge__(s, o): return (s.time, s.priority) >= (o.time, o.priority) +Event.time.__doc__ = ('''Numeric type compatible with the return value of the +timefunc function passed to the constructor.''') +Event.priority.__doc__ = ('''Events scheduled for the same time will be executed +in the order of their priority.''') +Event.action.__doc__ = ('''Executing the event means executing +action(*argument, **kwargs)''') +Event.argument.__doc__ = ('''argument is a sequence holding the positional +arguments for the action.''') +Event.kwargs.__doc__ = ('''kwargs is a dictionary holding the keyword +arguments for the action.''') + _sentinel = object() class scheduler: diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -43,9 +43,17 @@ SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data']) -"""Object used to associate a file object to its backing file descriptor, -selected event mask and attached data.""" +SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data) + + Object used to associate a file object to its backing + file descriptor, selected event mask, and attached data. +""" +SelectorKey.fileobj.__doc__ = 'File object registered.' +SelectorKey.fd.__doc__ = 'Underlying file descriptor.' +SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.' +SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object. +For example, this could be used to store a per-client session ID.''') class _SelectorMapping(Mapping): """Mapping of file objects to selector keys.""" diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -965,6 +965,9 @@ __all__.append('disk_usage') _ntuple_diskusage = collections.namedtuple('usage', 'total used free') + _ntuple_diskusage.total.__doc__ = 'Total space in bytes' + _ntuple_diskusage.used.__doc__ = 'Used space in bytes' + _ntuple_diskusage.free.__doc__ = 'Free space in bytes' def disk_usage(path): """Return disk usage statistics about the given path. diff --git a/Lib/sndhdr.py b/Lib/sndhdr.py --- a/Lib/sndhdr.py +++ b/Lib/sndhdr.py @@ -37,6 +37,18 @@ SndHeaders = namedtuple('SndHeaders', 'filetype framerate nchannels nframes sampwidth') +SndHeaders.filetype.__doc__ = ("""The value for type indicates the data type +and will be one of the strings 'aifc', 'aiff', 'au','hcom', +'sndr', 'sndt', 'voc', 'wav', '8svx', 'sb', 'ub', or 'ul'.""") +SndHeaders.framerate.__doc__ = ("""The sampling_rate will be either the actual +value or 0 if unknown or difficult to decode.""") +SndHeaders.nchannels.__doc__ = ("""The number of channels or 0 if it cannot be +determined or if the value is difficult to decode.""") +SndHeaders.nframes.__doc__ = ("""The value for frames will be either the number +of frames or -1.""") +SndHeaders.sampwidth.__doc__ = ("""Either the sample size in bits or +'A' for A-LAW or 'U' for u-LAW.""") + def what(filename): """Guess the type of a sound file.""" res = whathdr(filename) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 08:39:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 18 Aug 2015 06:39:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4_=28=2324883=29?= Message-ID: <20150818063921.6782.98695@psf.io> https://hg.python.org/cpython/rev/76892906253c changeset: 97430:76892906253c branch: 3.5 parent: 97426:637a9d6328f6 parent: 97429:0c5af3e398f0 user: Benjamin Peterson date: Mon Aug 17 23:38:46 2015 -0700 summary: merge 3.4 (#24883) files: Doc/c-api/buffer.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -133,15 +133,15 @@ called on non-NULL :c:member:`~Py_buffer.format` values. Important exception: If a consumer requests a buffer without the - :c:macro:`PyBUF_FORMAT` flag, :c:member:`~Py_Buffer.format` will + :c:macro:`PyBUF_FORMAT` flag, :c:member:`~Py_buffer.format` will be set to *NULL*, but :c:member:`~Py_buffer.itemsize` still has the value for the original format. - If :c:member:`~Py_Buffer.shape` is present, the equality + If :c:member:`~Py_buffer.shape` is present, the equality ``product(shape) * itemsize == len`` still holds and the consumer can use :c:member:`~Py_buffer.itemsize` to navigate the buffer. - If :c:member:`~Py_Buffer.shape` is *NULL* as a result of a :c:macro:`PyBUF_SIMPLE` + If :c:member:`~Py_buffer.shape` is *NULL* as a result of a :c:macro:`PyBUF_SIMPLE` or a :c:macro:`PyBUF_WRITABLE` request, the consumer must disregard :c:member:`~Py_buffer.itemsize` and assume ``itemsize == 1``. @@ -156,7 +156,7 @@ .. c:member:: int ndim The number of dimensions the memory represents as an n-dimensional array. - If it is 0, :c:member:`~Py_Buffer.buf` points to a single item representing + If it is 0, :c:member:`~Py_buffer.buf` points to a single item representing a scalar. In this case, :c:member:`~Py_buffer.shape`, :c:member:`~Py_buffer.strides` and :c:member:`~Py_buffer.suboffsets` MUST be *NULL*. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 08:39:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 18 Aug 2015 06:39:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogJ1B5X0J1ZmZlcicg?= =?utf-8?q?should_be_=27Py=5Fbuffer=27_=28closes_=2324883=29?= Message-ID: <20150818063920.6780.53409@psf.io> https://hg.python.org/cpython/rev/0c5af3e398f0 changeset: 97429:0c5af3e398f0 branch: 3.4 parent: 97423:ad0491f85050 user: Benjamin Peterson date: Mon Aug 17 23:38:34 2015 -0700 summary: 'Py_Buffer' should be 'Py_buffer' (closes #24883) files: Doc/c-api/buffer.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -133,15 +133,15 @@ called on non-NULL :c:member:`~Py_buffer.format` values. Important exception: If a consumer requests a buffer without the - :c:macro:`PyBUF_FORMAT` flag, :c:member:`~Py_Buffer.format` will + :c:macro:`PyBUF_FORMAT` flag, :c:member:`~Py_buffer.format` will be set to *NULL*, but :c:member:`~Py_buffer.itemsize` still has the value for the original format. - If :c:member:`~Py_Buffer.shape` is present, the equality + If :c:member:`~Py_buffer.shape` is present, the equality ``product(shape) * itemsize == len`` still holds and the consumer can use :c:member:`~Py_buffer.itemsize` to navigate the buffer. - If :c:member:`~Py_Buffer.shape` is *NULL* as a result of a :c:macro:`PyBUF_SIMPLE` + If :c:member:`~Py_buffer.shape` is *NULL* as a result of a :c:macro:`PyBUF_SIMPLE` or a :c:macro:`PyBUF_WRITABLE` request, the consumer must disregard :c:member:`~Py_buffer.itemsize` and assume ``itemsize == 1``. @@ -156,7 +156,7 @@ .. c:member:: int ndim The number of dimensions the memory represents as an n-dimensional array. - If it is 0, :c:member:`~Py_Buffer.buf` points to a single item representing + If it is 0, :c:member:`~Py_buffer.buf` points to a single item representing a scalar. In this case, :c:member:`~Py_buffer.shape`, :c:member:`~Py_buffer.strides` and :c:member:`~Py_buffer.suboffsets` MUST be *NULL*. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 08:39:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 18 Aug 2015 06:39:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41ICgjMjQ4ODMp?= Message-ID: <20150818063921.47402.17681@psf.io> https://hg.python.org/cpython/rev/c1e6bc6a9d69 changeset: 97431:c1e6bc6a9d69 parent: 97428:40f2bbb922e6 parent: 97430:76892906253c user: Benjamin Peterson date: Mon Aug 17 23:38:55 2015 -0700 summary: Merge 3.5 (#24883) files: Doc/c-api/buffer.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -133,15 +133,15 @@ called on non-NULL :c:member:`~Py_buffer.format` values. Important exception: If a consumer requests a buffer without the - :c:macro:`PyBUF_FORMAT` flag, :c:member:`~Py_Buffer.format` will + :c:macro:`PyBUF_FORMAT` flag, :c:member:`~Py_buffer.format` will be set to *NULL*, but :c:member:`~Py_buffer.itemsize` still has the value for the original format. - If :c:member:`~Py_Buffer.shape` is present, the equality + If :c:member:`~Py_buffer.shape` is present, the equality ``product(shape) * itemsize == len`` still holds and the consumer can use :c:member:`~Py_buffer.itemsize` to navigate the buffer. - If :c:member:`~Py_Buffer.shape` is *NULL* as a result of a :c:macro:`PyBUF_SIMPLE` + If :c:member:`~Py_buffer.shape` is *NULL* as a result of a :c:macro:`PyBUF_SIMPLE` or a :c:macro:`PyBUF_WRITABLE` request, the consumer must disregard :c:member:`~Py_buffer.itemsize` and assume ``itemsize == 1``. @@ -156,7 +156,7 @@ .. c:member:: int ndim The number of dimensions the memory represents as an n-dimensional array. - If it is 0, :c:member:`~Py_Buffer.buf` points to a single item representing + If it is 0, :c:member:`~Py_buffer.buf` points to a single item representing a scalar. In this case, :c:member:`~Py_buffer.shape`, :c:member:`~Py_buffer.strides` and :c:member:`~Py_buffer.suboffsets` MUST be *NULL*. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 08:55:55 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 18 Aug 2015 06:55:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_cleanups?= Message-ID: <20150818065534.47416.36396@psf.io> https://hg.python.org/cpython/rev/d600091be56c changeset: 97432:d600091be56c user: Raymond Hettinger date: Mon Aug 17 23:55:28 2015 -0700 summary: Minor cleanups files: Modules/itertoolsmodule.c | 156 ++++++++++++------------- 1 files changed, 74 insertions(+), 82 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1,17 +1,16 @@ #define PY_SSIZE_T_CLEAN - #include "Python.h" #include "structmember.h" /* Itertools module written and maintained by Raymond D. Hettinger - Copyright (c) 2003-2013 Python Software Foundation. + Copyright (c) 2003-2015 Python Software Foundation. All rights reserved. */ -/* groupby object ***********************************************************/ +/* groupby object ************************************************************/ typedef struct { PyObject_HEAD @@ -89,8 +88,7 @@ else { int rcmp; - rcmp = PyObject_RichCompareBool(gbo->tgtkey, - gbo->currkey, Py_EQ); + rcmp = PyObject_RichCompareBool(gbo->tgtkey, gbo->currkey, Py_EQ); if (rcmp == -1) return NULL; else if (rcmp == 0) @@ -105,8 +103,7 @@ newkey = newvalue; Py_INCREF(newvalue); } else { - newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, - newvalue, NULL); + newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL); if (newkey == NULL) { Py_DECREF(newvalue); return NULL; @@ -303,8 +300,7 @@ newkey = newvalue; Py_INCREF(newvalue); } else { - newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, - newvalue, NULL); + newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL); if (newkey == NULL) { Py_DECREF(newvalue); return NULL; @@ -332,8 +328,7 @@ static PyObject * _grouper_reduce(_grouperobject *lz) { - return Py_BuildValue("O(OO)", Py_TYPE(lz), - lz->parent, lz->tgtkey); + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->parent, lz->tgtkey); } static PyMethodDef _grouper_methods[] = { @@ -387,8 +382,7 @@ }; - -/* tee object and with supporting function and objects ***************/ +/* tee object and with supporting function and objects ***********************/ /* The teedataobject pre-allocates space for LINKCELLS number of objects. To help the object fit neatly inside cache lines (space for 16 to 32 @@ -403,7 +397,7 @@ typedef struct { PyObject_HEAD PyObject *it; - int numread; /* 0 <= numread <= LINKCELLS */ + int numread; /* 0 <= numread <= LINKCELLS */ PyObject *nextlink; PyObject *(values[LINKCELLS]); } teedataobject; @@ -411,7 +405,7 @@ typedef struct { PyObject_HEAD teedataobject *dataobj; - int index; /* 0 <= index <= LINKCELLS */ + int index; /* 0 <= index <= LINKCELLS */ PyObject *weakreflist; } teeobject; @@ -468,6 +462,7 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg) { int i; + Py_VISIT(tdo->it); for (i = 0; i < tdo->numread; i++) Py_VISIT(tdo->values[i]); @@ -517,6 +512,7 @@ int i; /* create a temporary list of already iterated values */ PyObject *values = PyList_New(tdo->numread); + if (!values) return NULL; for (i=0 ; inumread ; i++) { @@ -859,7 +855,7 @@ "tee(iterable, n=2) --> tuple of n independent iterators."); -/* cycle object **********************************************************/ +/* cycle object **************************************************************/ typedef struct { PyObject_HEAD @@ -989,6 +985,7 @@ { PyObject *saved=NULL; int firstpass; + if (!PyArg_ParseTuple(state, "O!i", &PyList_Type, &saved, &firstpass)) return NULL; Py_INCREF(saved); @@ -1064,7 +1061,7 @@ PyObject_HEAD PyObject *func; PyObject *it; - long start; + long start; } dropwhileobject; static PyTypeObject dropwhile_type; @@ -1154,8 +1151,7 @@ static PyObject * dropwhile_reduce(dropwhileobject *lz) { - return Py_BuildValue("O(OO)l", Py_TYPE(lz), - lz->func, lz->it, lz->start); + return Py_BuildValue("O(OO)l", Py_TYPE(lz), lz->func, lz->it, lz->start); } static PyObject * @@ -1233,7 +1229,7 @@ PyObject_HEAD PyObject *func; PyObject *it; - long stop; + long stop; } takewhileobject; static PyTypeObject takewhile_type; @@ -1308,7 +1304,7 @@ } ok = PyObject_IsTrue(good); Py_DECREF(good); - if (ok == 1) + if (ok > 0) return item; Py_DECREF(item); if (ok == 0) @@ -1319,14 +1315,14 @@ static PyObject * takewhile_reduce(takewhileobject *lz) { - return Py_BuildValue("O(OO)l", Py_TYPE(lz), - lz->func, lz->it, lz->stop); + return Py_BuildValue("O(OO)l", Py_TYPE(lz), lz->func, lz->it, lz->stop); } static PyObject * takewhile_reduce_setstate(takewhileobject *lz, PyObject *state) { int stop = PyObject_IsTrue(state); + if (stop < 0) return NULL; lz->stop = stop; @@ -1391,7 +1387,7 @@ }; -/* islice object ************************************************************/ +/* islice object *************************************************************/ typedef struct { PyObject_HEAD @@ -1549,6 +1545,7 @@ * then 'setstate' with the next and count */ PyObject *stop; + if (lz->it == NULL) { PyObject *empty_list; PyObject *empty_it; @@ -1578,6 +1575,7 @@ islice_setstate(isliceobject *lz, PyObject *state) { Py_ssize_t cnt = PyLong_AsSsize_t(state); + if (cnt == -1 && PyErr_Occurred()) return NULL; lz->cnt = cnt; @@ -1792,7 +1790,7 @@ }; -/* chain object ************************************************************/ +/* chain object **************************************************************/ typedef struct { PyObject_HEAD @@ -1919,6 +1917,7 @@ chain_setstate(chainobject *lz, PyObject *state) { PyObject *source, *active=NULL; + if (! PyArg_ParseTuple(state, "O|O", &source, &active)) return NULL; @@ -1945,8 +1944,8 @@ that evaluates lazily."); static PyMethodDef chain_methods[] = { - {"from_iterable", (PyCFunction) chain_new_from_iterable, METH_O | METH_CLASS, - chain_from_iterable_doc}, + {"from_iterable", (PyCFunction) chain_new_from_iterable, METH_O | METH_CLASS, + chain_from_iterable_doc}, {"__reduce__", (PyCFunction)chain_reduce, METH_NOARGS, reduce_doc}, {"__setstate__", (PyCFunction)chain_setstate, METH_O, @@ -2003,10 +2002,10 @@ typedef struct { PyObject_HEAD - PyObject *pools; /* tuple of pool tuples */ - Py_ssize_t *indices; /* one index per pool */ - PyObject *result; /* most recently returned result tuple */ - int stopped; /* set to 1 when the product iterator is exhausted */ + PyObject *pools; /* tuple of pool tuples */ + Py_ssize_t *indices; /* one index per pool */ + PyObject *result; /* most recently returned result tuple */ + int stopped; /* set to 1 when the iterator is exhausted */ } productobject; static PyTypeObject product_type; @@ -2025,7 +2024,8 @@ PyObject *tmpargs = PyTuple_New(0); if (tmpargs == NULL) return NULL; - if (!PyArg_ParseTupleAndKeywords(tmpargs, kwds, "|n:product", kwlist, &repeat)) { + if (!PyArg_ParseTupleAndKeywords(tmpargs, kwds, "|n:product", + kwlist, &repeat)) { Py_DECREF(tmpargs); return NULL; } @@ -2349,15 +2349,15 @@ }; -/* combinations object ************************************************************/ +/* combinations object *******************************************************/ typedef struct { PyObject_HEAD - PyObject *pool; /* input converted to a tuple */ - Py_ssize_t *indices; /* one index per result element */ - PyObject *result; /* most recently returned result tuple */ - Py_ssize_t r; /* size of result tuple */ - int stopped; /* set to 1 when the combinations iterator is exhausted */ + PyObject *pool; /* input converted to a tuple */ + Py_ssize_t *indices; /* one index per result element */ + PyObject *result; /* most recently returned result tuple */ + Py_ssize_t r; /* size of result tuple */ + int stopped; /* set to 1 when the iterator is exhausted */ } combinationsobject; static PyTypeObject combinations_type; @@ -2567,17 +2567,16 @@ Py_ssize_t i; Py_ssize_t n = PyTuple_GET_SIZE(lz->pool); - if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != lz->r) - { + if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) != lz->r) { PyErr_SetString(PyExc_ValueError, "invalid arguments"); return NULL; } - for (i=0; ir; i++) - { + for (i=0; ir; i++) { Py_ssize_t max; PyObject* indexObject = PyTuple_GET_ITEM(state, i); Py_ssize_t index = PyLong_AsSsize_t(indexObject); + if (index == -1 && PyErr_Occurred()) return NULL; /* not an integer */ max = i + n - lz->r; @@ -2664,7 +2663,7 @@ }; -/* combinations with replacement object *******************************************/ +/* combinations with replacement object **************************************/ /* Equivalent to: @@ -2694,11 +2693,11 @@ */ typedef struct { PyObject_HEAD - PyObject *pool; /* input converted to a tuple */ - Py_ssize_t *indices; /* one index per result element */ - PyObject *result; /* most recently returned result tuple */ - Py_ssize_t r; /* size of result tuple */ - int stopped; /* set to 1 when the cwr iterator is exhausted */ + PyObject *pool; /* input converted to a tuple */ + Py_ssize_t *indices; /* one index per result element */ + PyObject *result; /* most recently returned result tuple */ + Py_ssize_t r; /* size of result tuple */ + int stopped; /* set to 1 when the cwr iterator is exhausted */ } cwrobject; static PyTypeObject cwr_type; @@ -2715,8 +2714,9 @@ Py_ssize_t i; static char *kwargs[] = {"iterable", "r", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:combinations_with_replacement", kwargs, - &iterable, &r)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "On:combinations_with_replacement", + kwargs, &iterable, &r)) return NULL; pool = PySequence_Tuple(iterable); @@ -2881,8 +2881,7 @@ indices = PyTuple_New(lz->r); if (!indices) return NULL; - for (i=0; ir; i++) - { + for (i=0; ir; i++) { PyObject* index = PyLong_FromSsize_t(lz->indices[i]); if (!index) { Py_DECREF(indices); @@ -2908,10 +2907,10 @@ } n = PyTuple_GET_SIZE(lz->pool); - for (i=0; ir; i++) - { + for (i=0; ir; i++) { PyObject* indexObject = PyTuple_GET_ITEM(state, i); Py_ssize_t index = PyLong_AsSsize_t(indexObject); + if (index < 0 && PyErr_Occurred()) return NULL; /* not an integer */ /* clamp the index */ @@ -2996,7 +2995,7 @@ }; -/* permutations object ************************************************************ +/* permutations object ******************************************************** def permutations(iterable, r=None): 'permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)' @@ -3023,12 +3022,12 @@ typedef struct { PyObject_HEAD - PyObject *pool; /* input converted to a tuple */ - Py_ssize_t *indices; /* one index per element in the pool */ - Py_ssize_t *cycles; /* one rollover counter per element in the result */ - PyObject *result; /* most recently returned result tuple */ - Py_ssize_t r; /* size of result tuple */ - int stopped; /* set to 1 when the permutations iterator is exhausted */ + PyObject *pool; /* input converted to a tuple */ + Py_ssize_t *indices; /* one index per element in the pool */ + Py_ssize_t *cycles; /* one rollover counter per element in the result */ + PyObject *result; /* most recently returned result tuple */ + Py_ssize_t r; /* size of result tuple */ + int stopped; /* set to 1 when the iterator is exhausted */ } permutationsobject; static PyTypeObject permutations_type; @@ -3243,7 +3242,7 @@ indices = PyTuple_New(n); if (indices == NULL) goto err; - for (i=0; iindices[i]); if (!index) goto err; @@ -3253,8 +3252,7 @@ cycles = PyTuple_New(po->r); if (cycles == NULL) goto err; - for (i=0; ir; i++) - { + for (i=0 ; ir ; i++) { PyObject* index = PyLong_FromSsize_t(po->cycles[i]); if (!index) goto err; @@ -3282,15 +3280,12 @@ return NULL; n = PyTuple_GET_SIZE(po->pool); - if (PyTuple_GET_SIZE(indices) != n || - PyTuple_GET_SIZE(cycles) != po->r) - { + if (PyTuple_GET_SIZE(indices) != n || PyTuple_GET_SIZE(cycles) != po->r) { PyErr_SetString(PyExc_ValueError, "invalid arguments"); return NULL; } - for (i=0; iindices[i] = index; } - for (i=0; ir; i++) - { + for (i=0; ir; i++) { PyObject* indexObject = PyTuple_GET_ITEM(cycles, i); Py_ssize_t index = PyLong_AsSsize_t(indexObject); if (index < 0 && PyErr_Occurred()) @@ -3388,7 +3382,7 @@ PyObject_GC_Del, /* tp_free */ }; -/* accumulate object ************************************************************/ +/* accumulate object ********************************************************/ typedef struct { PyObject_HEAD @@ -3489,7 +3483,7 @@ return Py_BuildValue("O(OO)O", Py_TYPE(lz), lz->it, lz->binop?lz->binop:Py_None, lz->total?lz->total:Py_None); - } +} static PyObject * accumulate_setstate(accumulateobject *lz, PyObject *state) @@ -3652,7 +3646,7 @@ ok = PyObject_IsTrue(selector); Py_DECREF(selector); - if (ok == 1) + if (ok > 0) return datum; Py_DECREF(datum); if (ok < 0) @@ -3665,7 +3659,7 @@ { return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->data, lz->selectors); - } +} static PyMethodDef compress_methods[] = { {"__reduce__", (PyCFunction)compress_reduce, METH_NOARGS, @@ -3821,9 +3815,8 @@ static PyObject * filterfalse_reduce(filterfalseobject *lz) { - return Py_BuildValue("O(OO)", Py_TYPE(lz), - lz->func, lz->it); - } + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->func, lz->it); +} static PyMethodDef filterfalse_methods[] = { {"__reduce__", (PyCFunction)filterfalse_reduce, METH_NOARGS, @@ -4274,9 +4267,7 @@ PyObject_GC_Del, /* tp_free */ }; -/* ziplongest object ************************************************************/ - -#include "Python.h" +/* ziplongest object *********************************************************/ typedef struct { PyObject_HEAD @@ -4315,7 +4306,7 @@ ittuple = PyTuple_New(tuplesize); if (ittuple == NULL) return NULL; - for (i=0; i < tuplesize; ++i) { + for (i=0; i < tuplesize; i++) { PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *it = PyObject_GetIter(item); if (it == NULL) { @@ -4456,6 +4447,7 @@ */ int i; PyObject *args = PyTuple_New(PyTuple_GET_SIZE(lz->ittuple)); + if (args == NULL) return NULL; for (i=0; iittuple); i++) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 09:20:30 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 18 Aug 2015 07:20:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Inline_PyIter=5FNext=28=29?= =?utf-8?q?_matching_the_other_itertools_code=2E?= Message-ID: <20150818072030.13714.85492@psf.io> https://hg.python.org/cpython/rev/4fb847bc3de8 changeset: 97433:4fb847bc3de8 user: Raymond Hettinger date: Tue Aug 18 00:20:20 2015 -0700 summary: Inline PyIter_Next() matching the other itertools code. files: Python/bltinmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1164,7 +1164,8 @@ return NULL; for (i=0 ; iiters, i)); + PyObject *it = PyTuple_GET_ITEM(lz->iters, i); + val = Py_TYPE(it)->tp_iternext(it); if (val == NULL) { Py_DECREF(argtuple); return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 09:36:06 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 18 Aug 2015 07:36:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_docstring?= Message-ID: <20150818073606.13736.53603@psf.io> https://hg.python.org/cpython/rev/b42f6c930cea changeset: 97434:b42f6c930cea user: Raymond Hettinger date: Tue Aug 18 00:35:52 2015 -0700 summary: Add missing docstring files: Lib/urllib/request.py | 65 +++++++++++++++++++++++++++++++ 1 files changed, 65 insertions(+), 0 deletions(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -138,6 +138,71 @@ _opener = None def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *, cafile=None, capath=None, cadefault=False, context=None): + '''Open the URL url, which can be either a string or a Request object. + + *data* must be a bytes object specifying additional data to be sent to the + server, or None if no such data is needed. data may also be an iterable + object and in that case Content-Length value must be specified in the + headers. Currently HTTP requests are the only ones that use data; the HTTP + request will be a POST instead of a GET when the data parameter is + provided. + + *data* should be a buffer in the standard application/x-www-form-urlencoded + format. The urllib.parse.urlencode() function takes a mapping or sequence + of 2-tuples and returns a string in this format. It should be encoded to + bytes before being used as the data parameter. The charset parameter in + Content-Type header may be used to specify the encoding. If charset + parameter is not sent with the Content-Type header, the server following + the HTTP 1.1 recommendation may assume that the data is encoded in + ISO-8859-1 encoding. It is advisable to use charset parameter with encoding + used in Content-Type header with the Request. + + urllib.request module uses HTTP/1.1 and includes a "Connection:close" + header in its HTTP requests. + + The optional *timeout* parameter specifies a timeout in seconds for + blocking operations like the connection attempt (if not specified, the + global default timeout setting will be used). This only works for HTTP, + HTTPS and FTP connections. + + If *context* is specified, it must be a ssl.SSLContext instance describing + the various SSL options. See HTTPSConnection for more details. + + The optional *cafile* and *capath* parameters specify a set of trusted CA + certificates for HTTPS requests. cafile should point to a single file + containing a bundle of CA certificates, whereas capath should point to a + directory of hashed certificate files. More information can be found in + ssl.SSLContext.load_verify_locations(). + + The *cadefault* parameter is ignored. + + For http and https urls, this function returns a http.client.HTTPResponse + object which has the following HTTPResponse Objects methods. + + For ftp, file, and data urls and requests explicitly handled by legacy + URLopener and FancyURLopener classes, this function returns a + urllib.response.addinfourl object which can work as context manager and has + methods such as: + + * geturl() ? return the URL of the resource retrieved, commonly used to + determine if a redirect was followed + + * info() ? return the meta-information of the page, such as headers, in the + form of an email.message_from_string() instance (see Quick Reference to + HTTP Headers) + + * getcode() ? return the HTTP status code of the response. Raises URLError + on errors. + + Note that *None& may be returned if no handler handles the request (though + the default installed global OpenerDirector uses UnknownHandler to ensure + this never happens). + + In addition, if proxy settings are detected (for example, when a *_proxy + environment variable like http_proxy is set), ProxyHandler is default + installed and makes sure the requests are handled through the proxy. + + ''' global _opener if cafile or capath or cadefault: if context is not None: -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Tue Aug 18 13:38:52 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Tue, 18 Aug 2015 11:38:52 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-18 Message-ID: Results for project python_default-nightly, build date 2015-08-18 09:02:30 commit: 40f2bbb922e6dfb61c7950eda704f0a5cfbf4024 revision date: 2015-08-18 08:04:45 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 1.12735% 7.47953% :-( pybench sec -0.11537% -2.40978% :-( regex_v8 sec -0.00148% -3.47963% :-| nbody sec -0.40202% -1.35287% :-| json_dump_v2 sec -0.35161% -1.16376% :-| normal_startup sec 0.21169% 0.16097% -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Tue Aug 18 16:21:54 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 14:21:54 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-492=3A_Fix_example_code?= Message-ID: <20150818142127.91811.75595@psf.io> https://hg.python.org/peps/rev/e72bd4d00471 changeset: 5957:e72bd4d00471 user: Yury Selivanov date: Tue Aug 18 10:21:19 2015 -0400 summary: pep-492: Fix example code files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -507,7 +507,7 @@ def __init__(self): self.buffer = collections.deque() - def _prefetch(self): + async def _prefetch(self): ... async def __aiter__(self): -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 18 17:07:50 2015 From: python-checkins at python.org (raymond.hettinger) Date: Tue, 18 Aug 2015 15:07:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Use_PyTuple=5FGET=5FSIZE_l?= =?utf-8?q?ike_the_adjacent_code_does=2E?= Message-ID: <20150818150730.91827.56549@psf.io> https://hg.python.org/cpython/rev/f65729eb9147 changeset: 97435:f65729eb9147 user: Raymond Hettinger date: Tue Aug 18 08:07:16 2015 -0700 summary: Use PyTuple_GET_SIZE like the adjacent code does. files: Python/bltinmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1158,7 +1158,7 @@ PyObject *result; Py_ssize_t numargs, i; - numargs = PyTuple_Size(lz->iters); + numargs = PyTuple_GET_SIZE(lz->iters); argtuple = PyTuple_New(numargs); if (argtuple == NULL) return NULL; -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Tue Aug 18 18:26:22 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Tue, 18 Aug 2015 16:26:22 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-18 Message-ID: Please ignore the last email, and consider this one. Thank you! Results for project python_default-nightly, build date 2015-08-18 18:54:18 commit: f65729eb9147daeb189c94ccef845192904117ef revision date: 2015-08-18 18:07:16 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.19108% 1.12735% 7.47953% :-( pybench sec 0.18636% -0.00743% -2.41739% :-( regex_v8 sec 2.82513% -0.19635% -3.68281% :-| nbody sec 0.41387% 0.49458% -0.85161% :-| json_dump_v2 sec 0.21976% 0.40247% -0.75660% :-| normal_startup sec 0.93781% -0.19402% -0.03274% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Tue Aug 18 19:24:36 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Aug 2015 17:24:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_=28Merge_3=2E5=29_cgi=2EFieldStorage=2Eread=5Fmulti_igno?= =?utf-8?q?res_Content-Length?= Message-ID: <20150818172436.6302.69281@psf.io> https://hg.python.org/cpython/rev/0ff1acc89cf0 changeset: 97438:0ff1acc89cf0 parent: 97435:f65729eb9147 parent: 97437:5b9209e4c3e4 user: Victor Stinner date: Tue Aug 18 10:23:48 2015 -0700 summary: (Merge 3.5) cgi.FieldStorage.read_multi ignores Content-Length Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. files: Lib/cgi.py | 5 +++++ Lib/test/test_cgi.py | 18 ++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++++ 4 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Lib/cgi.py b/Lib/cgi.py --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -720,6 +720,11 @@ self.bytes_read += len(hdr_text) parser.feed(hdr_text.decode(self.encoding, self.errors)) headers = parser.close() + + # Some clients add Content-Length for part headers, ignore them + if 'content-length' in headers: + del headers['content-length'] + part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing,self.limit-self.bytes_read, self.encoding, self.errors) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -326,6 +326,24 @@ got = getattr(files[x], k) self.assertEqual(got, exp) + def test_fieldstorage_part_content_length(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 5 + +Larry +--JfISa01""" + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH': str(len(POSTDATA))} + fp = BytesIO(POSTDATA.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 1) + self.assertEqual(fs.list[0].name, 'submit-name') + self.assertEqual(fs.list[0].value, 'Larry') + def test_fieldstorage_as_context_manager(self): fp = BytesIO(b'x' * 10) env = {'REQUEST_METHOD': 'PUT'} diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -795,6 +795,7 @@ Valerie Lambert Jean-Baptiste "Jiba" Lamy Ronan Lamy +Peter Landry Torsten Landschoff ?ukasz Langa Tino Lange diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,10 @@ Library ------- +- Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length + header in part headers. Patch written by Peter Landry and reviewed by Pierre + Quentel. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 19:24:36 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Aug 2015 17:24:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_=28Merge_3=2E4=29_cgi=2EFieldStorage=2Eread=5Fmulti_ignores_Co?= =?utf-8?q?ntent-Length?= Message-ID: <20150818172436.6308.87390@psf.io> https://hg.python.org/cpython/rev/5b9209e4c3e4 changeset: 97437:5b9209e4c3e4 branch: 3.5 parent: 97430:76892906253c parent: 97436:11e9f34169d1 user: Victor Stinner date: Tue Aug 18 10:23:16 2015 -0700 summary: (Merge 3.4) cgi.FieldStorage.read_multi ignores Content-Length Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. files: Lib/cgi.py | 5 +++++ Lib/test/test_cgi.py | 18 ++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++++ 4 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Lib/cgi.py b/Lib/cgi.py --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -720,6 +720,11 @@ self.bytes_read += len(hdr_text) parser.feed(hdr_text.decode(self.encoding, self.errors)) headers = parser.close() + + # Some clients add Content-Length for part headers, ignore them + if 'content-length' in headers: + del headers['content-length'] + part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing,self.limit-self.bytes_read, self.encoding, self.errors) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -326,6 +326,24 @@ got = getattr(files[x], k) self.assertEqual(got, exp) + def test_fieldstorage_part_content_length(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 5 + +Larry +--JfISa01""" + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH': str(len(POSTDATA))} + fp = BytesIO(POSTDATA.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 1) + self.assertEqual(fs.list[0].name, 'submit-name') + self.assertEqual(fs.list[0].value, 'Larry') + def test_fieldstorage_as_context_manager(self): fp = BytesIO(b'x' * 10) env = {'REQUEST_METHOD': 'PUT'} diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -795,6 +795,7 @@ Valerie Lambert Jean-Baptiste "Jiba" Lamy Ronan Lamy +Peter Landry Torsten Landschoff ?ukasz Langa Tino Lange diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,10 @@ Library ------- +- Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length + header in part headers. Patch written by Peter Landry and reviewed by Pierre + Quentel. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 19:25:13 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Aug 2015 17:25:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogY2dpLkZpZWxkU3Rv?= =?utf-8?q?rage=2Eread=5Fmulti_ignores_Content-Length?= Message-ID: <20150818172436.91835.34382@psf.io> https://hg.python.org/cpython/rev/11e9f34169d1 changeset: 97436:11e9f34169d1 branch: 3.4 parent: 97429:0c5af3e398f0 user: Victor Stinner date: Tue Aug 18 10:21:10 2015 -0700 summary: cgi.FieldStorage.read_multi ignores Content-Length Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. files: Lib/cgi.py | 5 +++++ Lib/test/test_cgi.py | 19 +++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++++ 4 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/cgi.py b/Lib/cgi.py --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -714,6 +714,11 @@ self.bytes_read += len(hdr_text) parser.feed(hdr_text.decode(self.encoding, self.errors)) headers = parser.close() + + # Some clients add Content-Length for part headers, ignore them + if 'content-length' in headers: + del headers['content-length'] + part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing,self.limit-self.bytes_read, self.encoding, self.errors) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -326,6 +326,25 @@ got = getattr(files[x], k) self.assertEqual(got, exp) + def test_fieldstorage_part_content_length(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 5 + +Larry +--JfISa01""" + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH': str(len(POSTDATA))} + fp = BytesIO(POSTDATA.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 1) + self.assertEqual(fs.list[0].name, 'submit-name') + self.assertEqual(fs.list[0].value, 'Larry') + + _qs_result = { 'key1': 'value1', 'key2': ['value2x', 'value2y'], diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -773,6 +773,7 @@ Valerie Lambert Jean-Baptiste "Jiba" Lamy Ronan Lamy +Peter Landry Torsten Landschoff ?ukasz Langa Tino Lange diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -75,6 +75,10 @@ Library ------- +- Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length + header in part headers. Patch written by Peter Landry and reviewed by Pierre + Quentel. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 19:28:17 2015 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Aug 2015 17:28:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Nzkw?= =?utf-8?q?=3A_Remove_extraneous_code_=28which_also_create_2_=26_3_conflic?= =?utf-8?q?ts=29=2E?= Message-ID: <20150818172817.21668.7605@psf.io> https://hg.python.org/cpython/rev/010264c9ceae changeset: 97440:010264c9ceae branch: 3.4 parent: 97436:11e9f34169d1 user: Terry Jan Reedy date: Tue Aug 18 13:26:57 2015 -0400 summary: Issue #24790: Remove extraneous code (which also create 2 & 3 conflicts). files: Lib/idlelib/StackViewer.py | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -10,8 +10,7 @@ def StackBrowser(root, flist=None, tb=None, top=None): if top is None: - from tkinter import Toplevel - top = Toplevel(root) + top = tk.Toplevel(root) sc = ScrolledCanvas(top, bg="white", highlightthickness=0) sc.frame.pack(expand=1, fill="both") item = StackTreeItem(flist, tb) @@ -108,12 +107,9 @@ def IsExpandable(self): return len(self.object) > 0 - def keys(self): - return list(self.object.keys()) - def GetSubList(self): sublist = [] - for key in self.keys(): + for key in self.object.keys(): try: value = self.object[key] except KeyError: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 19:28:17 2015 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Aug 2015 17:28:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150818172817.13716.74875@psf.io> https://hg.python.org/cpython/rev/80b3930b86ef changeset: 97442:80b3930b86ef parent: 97438:0ff1acc89cf0 parent: 97441:01d91caa58b6 user: Terry Jan Reedy date: Tue Aug 18 13:27:30 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/StackViewer.py | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -10,8 +10,7 @@ def StackBrowser(root, flist=None, tb=None, top=None): if top is None: - from tkinter import Toplevel - top = Toplevel(root) + top = tk.Toplevel(root) sc = ScrolledCanvas(top, bg="white", highlightthickness=0) sc.frame.pack(expand=1, fill="both") item = StackTreeItem(flist, tb) @@ -108,12 +107,9 @@ def IsExpandable(self): return len(self.object) > 0 - def keys(self): - return list(self.object.keys()) - def GetSubList(self): sublist = [] - for key in self.keys(): + for key in self.object.keys(): try: value = self.object[key] except KeyError: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:19:14 2015 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Aug 2015 18:19:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150818172817.33575.40497@psf.io> https://hg.python.org/cpython/rev/01d91caa58b6 changeset: 97441:01d91caa58b6 branch: 3.5 parent: 97437:5b9209e4c3e4 parent: 97440:010264c9ceae user: Terry Jan Reedy date: Tue Aug 18 13:27:18 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/StackViewer.py | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -10,8 +10,7 @@ def StackBrowser(root, flist=None, tb=None, top=None): if top is None: - from tkinter import Toplevel - top = Toplevel(root) + top = tk.Toplevel(root) sc = ScrolledCanvas(top, bg="white", highlightthickness=0) sc.frame.pack(expand=1, fill="both") item = StackTreeItem(flist, tb) @@ -108,12 +107,9 @@ def IsExpandable(self): return len(self.object) > 0 - def keys(self): - return list(self.object.keys()) - def GetSubList(self): sublist = [] - for key in self.keys(): + for key in self.object.keys(): try: value = self.object[key] except KeyError: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:19:14 2015 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Aug 2015 18:19:14 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Nzkw?= =?utf-8?q?=3A_Remove_extraneous_code_=28which_also_create_2_=26_3_conflic?= =?utf-8?q?ts=29=2E?= Message-ID: <20150818172817.91835.76057@psf.io> https://hg.python.org/cpython/rev/9ad330a9d785 changeset: 97439:9ad330a9d785 branch: 2.7 parent: 97422:d3cda8cf4d42 user: Terry Jan Reedy date: Tue Aug 18 13:26:45 2015 -0400 summary: Issue #24790: Remove extraneous code (which also create 2 & 3 conflicts). files: Lib/idlelib/StackViewer.py | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -10,8 +10,7 @@ def StackBrowser(root, flist=None, tb=None, top=None): if top is None: - from Tkinter import Toplevel - top = Toplevel(root) + top = tk.Toplevel(root) sc = ScrolledCanvas(top, bg="white", highlightthickness=0) sc.frame.pack(expand=1, fill="both") item = StackTreeItem(flist, tb) @@ -108,12 +107,9 @@ def IsExpandable(self): return len(self.object) > 0 - def keys(self): - return self.object.keys() - def GetSubList(self): sublist = [] - for key in self.keys(): + for key in self.object.keys(): try: value = self.object[key] except KeyError: @@ -124,7 +120,7 @@ sublist.append(item) return sublist -def _stack_viewer(parent): +def _stack_viewer(parent): # htest # root = tk.Tk() root.title("Test StackViewer") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:26:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 18:26:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41IChpc3N1ZSAjMjM1NzIp?= Message-ID: <20150818182320.33575.98653@psf.io> https://hg.python.org/cpython/rev/94d0c219d46f changeset: 97444:94d0c219d46f parent: 97442:80b3930b86ef parent: 97443:73984e665bf5 user: Yury Selivanov date: Tue Aug 18 14:23:02 2015 -0400 summary: Merge 3.5 (issue #23572) files: Lib/functools.py | 2 +- Lib/test/test_functools.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -567,7 +567,7 @@ break # reject the current head, it appears later else: break - if not candidate: + if candidate is None: raise RuntimeError("Inconsistent hierarchy") result.append(candidate) # remove the chosen candidate diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1491,6 +1491,24 @@ many_abcs = [c.Mapping, c.Sized, c.Callable, c.Container, c.Iterable] self.assertEqual(mro(X, abcs=many_abcs), expected) + def test_false_meta(self): + # see issue23572 + class MetaA(type): + def __len__(self): + return 0 + class A(metaclass=MetaA): + pass + class AA(A): + pass + @functools.singledispatch + def fun(a): + return 'base A' + @fun.register(A) + def _(a): + return 'fun A' + aa = AA() + self.assertEqual(fun(aa), 'fun A') + def test_mro_conflicts(self): c = collections @functools.singledispatch -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:26:09 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 18:26:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIzNTcy?= =?utf-8?q?=3A_Fixed_functools=2Esingledispatch_on_classes_with_falsy_meta?= =?utf-8?q?classes=2E?= Message-ID: <20150818182320.6792.35139@psf.io> https://hg.python.org/cpython/rev/73984e665bf5 changeset: 97443:73984e665bf5 branch: 3.5 parent: 97441:01d91caa58b6 user: Yury Selivanov date: Tue Aug 18 14:20:00 2015 -0400 summary: Issue #23572: Fixed functools.singledispatch on classes with falsy metaclasses. Patch by Ethan Furman. files: Lib/functools.py | 2 +- Lib/test/test_functools.py | 18 ++++++++++++++++++ Misc/NEWS | 23 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -567,7 +567,7 @@ break # reject the current head, it appears later else: break - if not candidate: + if candidate is None: raise RuntimeError("Inconsistent hierarchy") result.append(candidate) # remove the chosen candidate diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1491,6 +1491,24 @@ many_abcs = [c.Mapping, c.Sized, c.Callable, c.Container, c.Iterable] self.assertEqual(mro(X, abcs=many_abcs), expected) + def test_false_meta(self): + # see issue23572 + class MetaA(type): + def __len__(self): + return 0 + class A(metaclass=MetaA): + pass + class AA(A): + pass + @functools.singledispatch + def fun(a): + return 'base A' + @fun.register(A) + def _(a): + return 'fun A' + aa = AA() + self.assertEqual(fun(aa), 'fun A') + def test_mro_conflicts(self): c = collections @functools.singledispatch diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,29 @@ Python News +++++++++++ + +What's New in Python 3.5.1 +========================== + + +Release date: TBA + + +Core and Builtins +----------------- + + +Library +------- + +- Issue #23572: Fixed functools.singledispatch on classes with falsy + metaclasses. Patch by Ethan Furman. + + +Documentation +------------- + + What's New in Python 3.5.0 release candidate 2? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:32:43 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 18:32:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Null_merge_=283=2E4=29?= Message-ID: <20150818183243.13714.86473@psf.io> https://hg.python.org/cpython/rev/678748b2a156 changeset: 97446:678748b2a156 branch: 3.5 parent: 97443:73984e665bf5 parent: 97445:586195685aaf user: Yury Selivanov date: Tue Aug 18 14:31:19 2015 -0400 summary: Null merge (3.4) files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:33:08 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 18:33:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNTcy?= =?utf-8?q?=3A_Fixed_functools=2Esingledispatch_on_classes_with_falsy_meta?= =?utf-8?q?classes=2E?= Message-ID: <20150818183243.91823.1399@psf.io> https://hg.python.org/cpython/rev/586195685aaf changeset: 97445:586195685aaf branch: 3.4 parent: 97440:010264c9ceae user: Yury Selivanov date: Tue Aug 18 14:30:15 2015 -0400 summary: Issue #23572: Fixed functools.singledispatch on classes with falsy metaclasses. Patch by Ethan Furman. files: Lib/functools.py | 2 +- Lib/test/test_functools.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py --- a/Lib/functools.py +++ b/Lib/functools.py @@ -551,7 +551,7 @@ break # reject the current head, it appears later else: break - if not candidate: + if candidate is None: raise RuntimeError("Inconsistent hierarchy") result.append(candidate) # remove the chosen candidate diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1328,6 +1328,24 @@ many_abcs = [c.Mapping, c.Sized, c.Callable, c.Container, c.Iterable] self.assertEqual(mro(X, abcs=many_abcs), expected) + def test_false_meta(self): + # see issue23572 + class MetaA(type): + def __len__(self): + return 0 + class A(metaclass=MetaA): + pass + class AA(A): + pass + @functools.singledispatch + def fun(a): + return 'base A' + @fun.register(A) + def _(a): + return 'fun A' + aa = AA() + self.assertEqual(fun(aa), 'fun A') + def test_mro_conflicts(self): c = collections @functools.singledispatch diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -392,6 +392,9 @@ - Issue #24298: Fix inspect.signature() to correctly unwrap wrappers around bound methods. +- Issue #23572: Fixed functools.singledispatch on classes with falsy + metaclasses. Patch by Ethan Furman. + IDLE ---- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 18 20:33:08 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Aug 2015 18:33:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTnVsbCBtZXJnZSAoMy41KQ==?= Message-ID: <20150818183243.47428.88353@psf.io> https://hg.python.org/cpython/rev/e3d41a07e845 changeset: 97447:e3d41a07e845 parent: 97444:94d0c219d46f parent: 97446:678748b2a156 user: Yury Selivanov date: Tue Aug 18 14:31:45 2015 -0400 summary: Null merge (3.5) files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 01:02:18 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 18 Aug 2015 23:02:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODQ3?= =?utf-8?q?=3A_Removes_vcruntime140=2Edll_dependency_from_Tcl/Tk=2E?= Message-ID: <20150818230218.4923.52424@psf.io> https://hg.python.org/cpython/rev/19ac02a522ba changeset: 97448:19ac02a522ba branch: 3.5 parent: 97446:678748b2a156 user: Steve Dower date: Tue Aug 18 16:00:56 2015 -0700 summary: Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. files: Misc/NEWS | 2 ++ PCbuild/get_externals.bat | 6 +++--- PCbuild/readme.txt | 2 +- PCbuild/tcl.vcxproj | 3 ++- PCbuild/tcltk.props | 4 ++-- PCbuild/tix.vcxproj | 6 ++---- PCbuild/tk.vcxproj | 4 ++-- Tools/msi/tcltk/tcltk.wixproj | 7 ------- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,8 @@ Library ------- +- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. + - Issue #23572: Fixed functools.singledispatch on classes with falsy metaclasses. Patch by Ethan Furman. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,9 +55,9 @@ bzip2-1.0.6 nasm-2.11.06 openssl-1.0.2d - tcl-core-8.6.4.1 - tk-8.6.4.1 - tix-8.4.3.4 + tcl-core-8.6.4.2 + tk-8.6.4.2 + tix-8.4.3.5 sqlite-3.8.11.0 xz-5.0.5 ) do ( diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -236,7 +236,7 @@ Homepage: http://www.sqlite.org/ _tkinter - Wraps version 8.6.1 of the Tk windowing system. + Wraps version 8.6.4 of the Tk windowing system. Homepage: http://www.tcl.tk/ diff --git a/PCbuild/tcl.vcxproj b/PCbuild/tcl.vcxproj --- a/PCbuild/tcl.vcxproj +++ b/PCbuild/tcl.vcxproj @@ -61,7 +61,8 @@ - symbols + ucrt + symbols,ucrt INSTALLDIR="$(OutDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -5,7 +5,7 @@ 8 6 4 - 1 + 2 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) @@ -13,7 +13,7 @@ 8 4 3 - 4 + 5 $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -56,11 +56,9 @@ - msvcrt - symbols,msvcrt BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 TCL_DBGX=g DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" - DEBUG=0 NODEBUG=1 + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=tg TK_DBGX=tg + DEBUG=0 NODEBUG=1 UCRT=1 TCL_DBGX=t TK_DBGX=t setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') diff --git a/PCbuild/tk.vcxproj b/PCbuild/tk.vcxproj --- a/PCbuild/tk.vcxproj +++ b/PCbuild/tk.vcxproj @@ -60,8 +60,8 @@ - msvcrt - symbols,msvcrt + ucrt + symbols,ucrt TCLDIR="$(tclDir.TrimEnd(`\`))" INSTALLDIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -27,13 +27,6 @@ DLLs\ tcltk_dlls - - $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ - $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ - $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ - DLLs\ - tcltk_dlls - $(tcltkDir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 01:02:42 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 18 Aug 2015 23:02:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150818230218.6790.20200@psf.io> https://hg.python.org/cpython/rev/a58aace8395a changeset: 97449:a58aace8395a parent: 97447:e3d41a07e845 parent: 97448:19ac02a522ba user: Steve Dower date: Tue Aug 18 16:01:25 2015 -0700 summary: Merge with 3.5 files: PCbuild/get_externals.bat | 6 +++--- PCbuild/readme.txt | 2 +- PCbuild/tcl.vcxproj | 3 ++- PCbuild/tcltk.props | 4 ++-- PCbuild/tix.vcxproj | 6 ++---- PCbuild/tk.vcxproj | 4 ++-- Tools/msi/tcltk/tcltk.wixproj | 7 ------- 7 files changed, 12 insertions(+), 20 deletions(-) diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,9 +55,9 @@ bzip2-1.0.6 nasm-2.11.06 openssl-1.0.2d - tcl-core-8.6.4.1 - tk-8.6.4.1 - tix-8.4.3.4 + tcl-core-8.6.4.2 + tk-8.6.4.2 + tix-8.4.3.5 sqlite-3.8.11.0 xz-5.0.5 ) do ( diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -236,7 +236,7 @@ Homepage: http://www.sqlite.org/ _tkinter - Wraps version 8.6.1 of the Tk windowing system. + Wraps version 8.6.4 of the Tk windowing system. Homepage: http://www.tcl.tk/ diff --git a/PCbuild/tcl.vcxproj b/PCbuild/tcl.vcxproj --- a/PCbuild/tcl.vcxproj +++ b/PCbuild/tcl.vcxproj @@ -61,7 +61,8 @@ - symbols + ucrt + symbols,ucrt INSTALLDIR="$(OutDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -5,7 +5,7 @@ 8 6 4 - 1 + 2 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) @@ -13,7 +13,7 @@ 8 4 3 - 4 + 5 $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -56,11 +56,9 @@ - msvcrt - symbols,msvcrt BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 TCL_DBGX=g DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" - DEBUG=0 NODEBUG=1 + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=tg TK_DBGX=tg + DEBUG=0 NODEBUG=1 UCRT=1 TCL_DBGX=t TK_DBGX=t setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') diff --git a/PCbuild/tk.vcxproj b/PCbuild/tk.vcxproj --- a/PCbuild/tk.vcxproj +++ b/PCbuild/tk.vcxproj @@ -60,8 +60,8 @@ - msvcrt - symbols,msvcrt + ucrt + symbols,ucrt TCLDIR="$(tclDir.TrimEnd(`\`))" INSTALLDIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -27,13 +27,6 @@ DLLs\ tcltk_dlls - - $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ - $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ - $(VCInstallDir)redist\$(Platform)\Microsoft.VC$(PlatformToolset.Substring(1)).CRT\ - DLLs\ - tcltk_dlls - $(tcltkDir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 02:20:46 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 19 Aug 2015 00:20:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324054=3A_decouple?= =?utf-8?q?_linecache_tests_from_inspect_tests?= Message-ID: <20150819002046.13732.85885@psf.io> https://hg.python.org/cpython/rev/fc56a0300cd4 changeset: 97450:fc56a0300cd4 user: Robert Collins date: Wed Aug 19 12:20:37 2015 +1200 summary: Issue #24054: decouple linecache tests from inspect tests Patch from David D. Riddle files: Lib/test/test_linecache.py | 74 ++++++++++++++++++++++--- 1 files changed, 63 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -3,6 +3,7 @@ import linecache import unittest import os.path +import tempfile from test import support @@ -10,8 +11,6 @@ NONEXISTENT_FILENAME = FILENAME + '.missing' INVALID_NAME = '!@$)(!@#_1' EMPTY = '' -TESTS = 'inspect_fodder inspect_fodder2 mapping_tests' -TESTS = TESTS.split() TEST_PATH = os.path.dirname(__file__) MODULES = "linecache abc".split() MODULE_PATH = os.path.dirname(FILENAME) @@ -37,6 +36,65 @@ return 3''' # No ending newline +class TempFile: + + def setUp(self): + super().setUp() + with tempfile.NamedTemporaryFile(delete=False) as fp: + self.file_name = fp.name + fp.write(self.file_byte_string) + self.addCleanup(support.unlink, self.file_name) + + +class GetLineTestsGoodData(TempFile): + # file_list = ['list\n', 'of\n', 'good\n', 'strings\n'] + + def setUp(self): + self.file_byte_string = ''.join(self.file_list).encode('utf-8') + super().setUp() + + def test_getline(self): + with open(self.file_name) as fp: + for index, line in enumerate(fp): + if not line.endswith('\n'): + line += '\n' + + cached_line = linecache.getline(self.file_name, index + 1) + self.assertEqual(line, cached_line) + + def test_getlines(self): + lines = linecache.getlines(self.file_name) + self.assertEqual(lines, self.file_list) + + +class GetLineTestsBadData(TempFile): + # file_byte_string = b'Bad data goes here' + + def test_getline(self): + self.assertRaises((SyntaxError, UnicodeDecodeError), + linecache.getline, self.file_name, 1) + + def test_getlines(self): + self.assertRaises((SyntaxError, UnicodeDecodeError), + linecache.getlines, self.file_name) + + +class EmptyFile(GetLineTestsGoodData, unittest.TestCase): + file_list = [] + + +class SingleEmptyLine(GetLineTestsGoodData, unittest.TestCase): + file_list = ['\n'] + + +class GoodUnicode(GetLineTestsGoodData, unittest.TestCase): + file_list = ['?\n', 'b\n', 'abcdef\n', '?????\n'] + + +class BadUnicode(GetLineTestsBadData, unittest.TestCase): + file_byte_string = b'\x80abc' + + class LineCacheTests(unittest.TestCase): def test_getline(self): @@ -53,13 +111,6 @@ self.assertEqual(getline(EMPTY, 1), EMPTY) self.assertEqual(getline(INVALID_NAME, 1), EMPTY) - # Check whether lines correspond to those from file iteration - for entry in TESTS: - filename = os.path.join(TEST_PATH, entry) + '.py' - with open(filename) as file: - for index, line in enumerate(file): - self.assertEqual(line, getline(filename, index + 1)) - # Check module loading for entry in MODULES: filename = os.path.join(MODULE_PATH, entry) + '.py' @@ -80,12 +131,13 @@ def test_clearcache(self): cached = [] - for entry in TESTS: - filename = os.path.join(TEST_PATH, entry) + '.py' + for entry in MODULES: + filename = os.path.join(MODULE_PATH, entry) + '.py' cached.append(filename) linecache.getline(filename, 1) # Are all files cached? + self.assertNotEqual(cached, []) cached_empty = [fn for fn in cached if fn not in linecache.cache] self.assertEqual(cached_empty, []) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 04:31:01 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 19 Aug 2015 02:31:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324847=3A_Fixes_Tix_revision_number_and_reverts_?= =?utf-8?q?fix_for_the_wrong_revision=2E?= Message-ID: <20150819023101.13724.76772@psf.io> https://hg.python.org/cpython/rev/9cc3f2f2d810 changeset: 97452:9cc3f2f2d810 parent: 97450:fc56a0300cd4 parent: 97451:0e2620831f17 user: Steve Dower date: Tue Aug 18 19:30:13 2015 -0700 summary: Issue #24847: Fixes Tix revision number and reverts fix for the wrong revision. Triggers clean on buildbots. files: PCbuild/get_externals.bat | 2 +- PCbuild/tcltk.props | 2 +- PCbuild/tix.vcxproj | 4 ++-- Tools/buildbot/build.bat | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -57,7 +57,7 @@ openssl-1.0.2d tcl-core-8.6.4.2 tk-8.6.4.2 - tix-8.4.3.5 + tix-8.4.3.6 sqlite-3.8.11.0 xz-5.0.5 ) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -13,7 +13,7 @@ 8 4 3 - 5 + 6 $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -57,8 +57,8 @@ BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=tg TK_DBGX=tg - DEBUG=0 NODEBUG=1 UCRT=1 TCL_DBGX=t TK_DBGX=t + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=g TK_DBGX=g + DEBUG=0 NODEBUG=1 UCRT=1 setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -7,7 +7,7 @@ @rem a new version of an external library, especially Tcl/Tk): @rem 1) uncomment the following line: - at rem call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only +call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only @rem 2) commit and push @rem 3) wait for all Windows bots to start a build with that changeset -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 04:31:24 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 19 Aug 2015 02:31:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODQ3?= =?utf-8?q?=3A_Fixes_Tix_revision_number_and_reverts_fix_for_the_wrong_rev?= =?utf-8?q?ision=2E?= Message-ID: <20150819023101.6794.10083@psf.io> https://hg.python.org/cpython/rev/0e2620831f17 changeset: 97451:0e2620831f17 branch: 3.5 parent: 97448:19ac02a522ba user: Steve Dower date: Tue Aug 18 19:29:51 2015 -0700 summary: Issue #24847: Fixes Tix revision number and reverts fix for the wrong revision. Triggers clean on buildbots. files: PCbuild/get_externals.bat | 2 +- PCbuild/tcltk.props | 2 +- PCbuild/tix.vcxproj | 4 ++-- Tools/buildbot/build.bat | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -57,7 +57,7 @@ openssl-1.0.2d tcl-core-8.6.4.2 tk-8.6.4.2 - tix-8.4.3.5 + tix-8.4.3.6 sqlite-3.8.11.0 xz-5.0.5 ) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -13,7 +13,7 @@ 8 4 3 - 5 + 6 $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -57,8 +57,8 @@ BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=tg TK_DBGX=tg - DEBUG=0 NODEBUG=1 UCRT=1 TCL_DBGX=t TK_DBGX=t + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=g TK_DBGX=g + DEBUG=0 NODEBUG=1 UCRT=1 setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -7,7 +7,7 @@ @rem a new version of an external library, especially Tcl/Tk): @rem 1) uncomment the following line: - at rem call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only +call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only @rem 2) commit and push @rem 3) wait for all Windows bots to start a build with that changeset -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 07:03:13 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 19 Aug 2015 05:03:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_in_missing_docstrings?= =?utf-8?q?=2E?= Message-ID: <20150819050313.15623.71793@psf.io> https://hg.python.org/cpython/rev/e10a34f8c23f changeset: 97453:e10a34f8c23f user: Raymond Hettinger date: Tue Aug 18 22:03:08 2015 -0700 summary: Add in missing docstrings. files: Lib/http/client.py | 49 ++++++++++++++++++++++++++++++++++ 1 files changed, 49 insertions(+), 0 deletions(-) diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -405,6 +405,7 @@ self.fp.flush() def readable(self): + """Always returns True""" return True # End of "raw stream" methods @@ -452,6 +453,10 @@ return s def readinto(self, b): + """Read up to len(b) bytes into bytearray b and return the number + of bytes read. + """ + if self.fp is None: return 0 @@ -683,6 +688,17 @@ return self.fp.fileno() def getheader(self, name, default=None): + '''Returns the value of the header matching *name*. + + If there are multiple matching headers, the values are + combined into a single string separated by commas and spaces. + + If no matching header is found, returns *default* or None if + the *default* is not specified. + + If the headers are unknown, raises http.client.ResponseNotReady. + + ''' if self.headers is None: raise ResponseNotReady() headers = self.headers.get_all(name) or default @@ -705,12 +721,45 @@ # For compatibility with old-style urllib responses. def info(self): + '''Returns an instance of the class mimetools.Message containing + meta-information associated with the URL. + + When the method is HTTP, these headers are those returned by + the server at the head of the retrieved HTML page (including + Content-Length and Content-Type). + + When the method is FTP, a Content-Length header will be + present if (as is now usual) the server passed back a file + length in response to the FTP retrieval request. A + Content-Type header will be present if the MIME type can be + guessed. + + When the method is local-file, returned headers will include + a Date representing the file?s last-modified time, a + Content-Length giving file size, and a Content-Type + containing a guess at the file?s type. See also the + description of the mimetools module. + + ''' return self.headers def geturl(self): + '''Return the real URL of the page. + + In some cases, the HTTP server redirects a client to another + URL. The urlopen() function handles this transparently, but in + some cases the caller needs to know which URL the client was + redirected to. The geturl() method can be used to get at this + redirected URL. + + ''' return self.url def getcode(self): + '''Return the HTTP status code that was sent with the response, + or None if the URL is not an HTTP URL. + + ''' return self.status class HTTPConnection: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 07:25:51 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 19 Aug 2015 05:25:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324879=3A__Teach_p?= =?utf-8?q?ydoc_to_display_named_tuple_fields_in_the_order_they_were?= Message-ID: <20150819052528.36747.51160@psf.io> https://hg.python.org/cpython/rev/f5c40ab9e233 changeset: 97454:f5c40ab9e233 user: Raymond Hettinger date: Tue Aug 18 22:25:16 2015 -0700 summary: Issue #24879: Teach pydoc to display named tuple fields in the order they were defined. files: Lib/pydoc.py | 19 +++++++++++++++---- Lib/test/test_pydoc.py | 16 ++++++++++++++++ Misc/NEWS | 4 ++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -209,6 +209,18 @@ results.append((name, kind, cls, value)) return results +def sort_attributes(attrs, object): + 'Sort the attrs list in-place by _fields and then alphabetically by name' + # This allows data descriptors to be ordered according + # to a _fields attribute if present. + fields = getattr(object, '_fields', []) + try: + field_order = {name : i-len(fields) for (i, name) in enumerate(fields)} + except TypeError: + field_order = {} + keyfunc = lambda attr: (field_order.get(attr[0], 0), attr[0]) + attrs.sort(key=keyfunc) + # ----------------------------------------------------- module manipulation def ispackage(path): @@ -867,8 +879,7 @@ object.__module__) tag += ':
\n' - # Sort attrs by name. - attrs.sort(key=lambda t: t[0]) + sort_attributes(attrs, object) # Pump out the attrs, segregated by kind. attrs = spill('Methods %s' % tag, attrs, @@ -1286,8 +1297,8 @@ else: tag = "inherited from %s" % classname(thisclass, object.__module__) - # Sort attrs by name. - attrs.sort() + + sort_attributes(attrs, object) # Pump out the attrs, segregated by kind. attrs = spill("Methods %s:\n" % tag, attrs, diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -811,6 +811,22 @@ self.assertEqual(self._get_summary_line(t.wrap), "wrap(text) method of textwrap.TextWrapper instance") + def test_field_order_for_named_tuples(self): + Person = namedtuple('Person', ['nickname', 'firstname', 'agegroup']) + s = pydoc.render_doc(Person) + self.assertLess(s.index('nickname'), s.index('firstname')) + self.assertLess(s.index('firstname'), s.index('agegroup')) + + class NonIterableFields: + _fields = None + + class NonHashableFields: + _fields = [[]] + + # Make sure these doesn't fail + pydoc.render_doc(NonIterableFields) + pydoc.render_doc(NonHashableFields) + @requires_docstrings def test_bound_builtin_method(self): s = StringIO() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,10 @@ header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. +- Issue #24879: help() and pydoc can now list named tuple fields in the + order they were defined rather than alphabetically. The ordering is + determined by the _fields attribute if present. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Wed Aug 19 14:28:43 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Wed, 19 Aug 2015 12:28:43 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-19 Message-ID: Results for project python_default-nightly, build date 2015-08-19 09:02:23 commit: f5c40ab9e2337b309d6a2ed4f6b9702660813764 revision date: 2015-08-19 08:25:16 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.19108% 1.12735% 7.47953% :-( pybench sec 0.15727% 0.06691% -2.34887% :-( regex_v8 sec 2.87066% 0.32590% -3.34491% :-| nbody sec 0.27727% -0.35899% -1.21365% :-| json_dump_v2 sec 0.18764% 0.76479% 0.01397% :-| normal_startup sec 0.97526% -0.23975% -0.27257% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Wed Aug 19 15:54:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Aug 2015 13:54:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Further_improv?= =?utf-8?q?e_os=2Epath=2Ecommonprefix=28=29_docs=2E?= Message-ID: <20150819135401.4931.54310@psf.io> https://hg.python.org/cpython/rev/b5b46f796964 changeset: 97455:b5b46f796964 branch: 3.5 parent: 97451:0e2620831f17 user: Yury Selivanov date: Wed Aug 19 09:53:28 2015 -0400 summary: Further improve os.path.commonprefix() docs. Patch by Serhiy Storchaka. files: Doc/library/os.path.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -92,11 +92,11 @@ :: - >>> os.path.commonprefix(['/dir1/dir2', '/dir3/dir4']) - '/dir' + >>> os.path.commonprefix(['/usr/lib', '/usr/local/lib']) + '/usr/l' - >>> os.path.commonpath(['/dir1/dir2', '/dir3/dir4']) - '/' + >>> os.path.commonpath(['/usr/lib', '/usr/local/lib']) + '/usr' .. function:: dirname(path) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 15:54:05 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Aug 2015 13:54:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150819135401.119064.27570@psf.io> https://hg.python.org/cpython/rev/c1bcb0534ba0 changeset: 97456:c1bcb0534ba0 parent: 97454:f5c40ab9e233 parent: 97455:b5b46f796964 user: Yury Selivanov date: Wed Aug 19 09:53:41 2015 -0400 summary: Merge 3.5 files: Doc/library/os.path.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -92,11 +92,11 @@ :: - >>> os.path.commonprefix(['/dir1/dir2', '/dir3/dir4']) - '/dir' + >>> os.path.commonprefix(['/usr/lib', '/usr/local/lib']) + '/usr/l' - >>> os.path.commonpath(['/dir1/dir2', '/dir3/dir4']) - '/' + >>> os.path.commonpath(['/usr/lib', '/usr/local/lib']) + '/usr' .. function:: dirname(path) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 17:08:36 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 19 Aug 2015 15:08:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Removes_--clea?= =?utf-8?q?n-only_option_from_buildbots=2E?= Message-ID: <20150819150507.118861.77374@psf.io> https://hg.python.org/cpython/rev/4b92b1a1ad27 changeset: 97457:4b92b1a1ad27 branch: 3.5 parent: 97455:b5b46f796964 user: Steve Dower date: Tue Aug 18 20:02:07 2015 -0700 summary: Removes --clean-only option from buildbots. files: Tools/buildbot/build.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -7,7 +7,7 @@ @rem a new version of an external library, especially Tcl/Tk): @rem 1) uncomment the following line: -call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only + at rem call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only @rem 2) commit and push @rem 3) wait for all Windows bots to start a build with that changeset -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 19 17:08:36 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 19 Aug 2015 15:08:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Removes_--clean-only_option_from_buildbots=2E?= Message-ID: <20150819150507.52771.28645@psf.io> https://hg.python.org/cpython/rev/70757af86c12 changeset: 97458:70757af86c12 parent: 97456:c1bcb0534ba0 parent: 97457:4b92b1a1ad27 user: Steve Dower date: Wed Aug 19 08:04:31 2015 -0700 summary: Removes --clean-only option from buildbots. files: Tools/buildbot/build.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -7,7 +7,7 @@ @rem a new version of an external library, especially Tcl/Tk): @rem 1) uncomment the following line: -call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only + at rem call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only @rem 2) commit and push @rem 3) wait for all Windows bots to start a build with that changeset -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 20 00:48:56 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 19 Aug 2015 22:48:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_test=5Flinecache_chang?= =?utf-8?q?e=2E?= Message-ID: <20150819224856.13736.44839@psf.io> https://hg.python.org/cpython/rev/2a0c04260bd4 changeset: 97459:2a0c04260bd4 user: Robert Collins date: Thu Aug 20 10:48:46 2015 +1200 summary: Fix test_linecache change. In non-UTF8 locales open() will have the wrong encoding for the test data. We need to open the file via tokenize, to get a detected encoding instead. files: Lib/test/test_linecache.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -4,6 +4,7 @@ import unittest import os.path import tempfile +import tokenize from test import support @@ -54,7 +55,7 @@ super().setUp() def test_getline(self): - with open(self.file_name) as fp: + with tokenize.open(self.file_name) as fp: for index, line in enumerate(fp): if not line.endswith('\n'): line += '\n' -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 20 01:14:05 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 19 Aug 2015 23:14:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzIwMzYy?= =?utf-8?q?=3A_Honour_TestCase=2ElongMessage_correctly_in_assertRegex=2E?= Message-ID: <20150819231359.52745.96972@psf.io> https://hg.python.org/cpython/rev/738de9a9a3ea changeset: 97460:738de9a9a3ea branch: 3.5 parent: 97457:4b92b1a1ad27 user: Robert Collins date: Thu Aug 20 11:13:09 2015 +1200 summary: Issue #20362: Honour TestCase.longMessage correctly in assertRegex. Patch from Ilia Kurenkov. files: Lib/unittest/case.py | 18 +++++++++------ Lib/unittest/test/test_assertions.py | 15 ++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 ++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -1279,8 +1279,10 @@ assert expected_regex, "expected_regex must not be empty." expected_regex = re.compile(expected_regex) if not expected_regex.search(text): - msg = msg or "Regex didn't match" - msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text) + standardMsg = "Regex didn't match: %r not found in %r" % ( + expected_regex.pattern, text) + # _formatMessage ensures the longMessage option is respected + msg = self._formatMessage(msg, standardMsg) raise self.failureException(msg) def assertNotRegex(self, text, unexpected_regex, msg=None): @@ -1289,11 +1291,12 @@ unexpected_regex = re.compile(unexpected_regex) match = unexpected_regex.search(text) if match: - msg = msg or "Regex matched" - msg = '%s: %r matches %r in %r' % (msg, - text[match.start():match.end()], - unexpected_regex.pattern, - text) + standardMsg = 'Regex matched: %r matches %r in %r' % ( + text[match.start() : match.end()], + unexpected_regex.pattern, + text) + # _formatMessage ensures the longMessage option is respected + msg = self._formatMessage(msg, standardMsg) raise self.failureException(msg) @@ -1315,6 +1318,7 @@ failIf = _deprecate(assertFalse) assertRaisesRegexp = _deprecate(assertRaisesRegex) assertRegexpMatches = _deprecate(assertRegex) + assertNotRegexpMatches = _deprecate(assertNotRegex) diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py --- a/Lib/unittest/test/test_assertions.py +++ b/Lib/unittest/test/test_assertions.py @@ -133,7 +133,6 @@ try: self.assertNotRegex('Ala ma kota', r'k.t', 'Message') except self.failureException as e: - self.assertIn("'kot'", e.args[0]) self.assertIn('Message', e.args[0]) else: self.fail('assertNotRegex should have failed.') @@ -329,6 +328,20 @@ "^unexpectedly identical: None$", "^unexpectedly identical: None : oops$"]) + def testAssertRegex(self): + self.assertMessages('assertRegex', ('foo', 'bar'), + ["^Regex didn't match:", + "^oops$", + "^Regex didn't match:", + "^Regex didn't match: (.*) : oops$"]) + + def testAssertNotRegex(self): + self.assertMessages('assertNotRegex', ('foo', 'foo'), + ["^Regex matched:", + "^oops$", + "^Regex matched:", + "^Regex matched: (.*) : oops$"]) + def assertMessagesCM(self, methodName, args, func, errors): """ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -786,6 +786,7 @@ Dave Kuhlman Jon Kuhn Toshio Kuratomi +Ilia Kurenkov Vladimir Kushnir Erno Kuusela Ross Lagerwall diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,9 @@ Library ------- +- Issue #20362: Honour TestCase.longMessage correctly in assertRegex. + Patch from Ilia Kurenkov. + - Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. - Issue #23572: Fixed functools.singledispatch on classes with falsy -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 20 01:14:05 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 19 Aug 2015 23:14:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320362=3A_Honour_TestCase=2ElongMessage_correctl?= =?utf-8?q?y_in_assertRegex=2E?= Message-ID: <20150819231359.118749.13739@psf.io> https://hg.python.org/cpython/rev/977e60f597de changeset: 97461:977e60f597de parent: 97459:2a0c04260bd4 parent: 97460:738de9a9a3ea user: Robert Collins date: Thu Aug 20 11:13:38 2015 +1200 summary: Issue #20362: Honour TestCase.longMessage correctly in assertRegex. Patch from Ilia Kurenkov. files: Lib/unittest/case.py | 18 +++++++++------ Lib/unittest/test/test_assertions.py | 15 ++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 ++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -1279,8 +1279,10 @@ assert expected_regex, "expected_regex must not be empty." expected_regex = re.compile(expected_regex) if not expected_regex.search(text): - msg = msg or "Regex didn't match" - msg = '%s: %r not found in %r' % (msg, expected_regex.pattern, text) + standardMsg = "Regex didn't match: %r not found in %r" % ( + expected_regex.pattern, text) + # _formatMessage ensures the longMessage option is respected + msg = self._formatMessage(msg, standardMsg) raise self.failureException(msg) def assertNotRegex(self, text, unexpected_regex, msg=None): @@ -1289,11 +1291,12 @@ unexpected_regex = re.compile(unexpected_regex) match = unexpected_regex.search(text) if match: - msg = msg or "Regex matched" - msg = '%s: %r matches %r in %r' % (msg, - text[match.start():match.end()], - unexpected_regex.pattern, - text) + standardMsg = 'Regex matched: %r matches %r in %r' % ( + text[match.start() : match.end()], + unexpected_regex.pattern, + text) + # _formatMessage ensures the longMessage option is respected + msg = self._formatMessage(msg, standardMsg) raise self.failureException(msg) @@ -1315,6 +1318,7 @@ failIf = _deprecate(assertFalse) assertRaisesRegexp = _deprecate(assertRaisesRegex) assertRegexpMatches = _deprecate(assertRegex) + assertNotRegexpMatches = _deprecate(assertNotRegex) diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py --- a/Lib/unittest/test/test_assertions.py +++ b/Lib/unittest/test/test_assertions.py @@ -133,7 +133,6 @@ try: self.assertNotRegex('Ala ma kota', r'k.t', 'Message') except self.failureException as e: - self.assertIn("'kot'", e.args[0]) self.assertIn('Message', e.args[0]) else: self.fail('assertNotRegex should have failed.') @@ -329,6 +328,20 @@ "^unexpectedly identical: None$", "^unexpectedly identical: None : oops$"]) + def testAssertRegex(self): + self.assertMessages('assertRegex', ('foo', 'bar'), + ["^Regex didn't match:", + "^oops$", + "^Regex didn't match:", + "^Regex didn't match: (.*) : oops$"]) + + def testAssertNotRegex(self): + self.assertMessages('assertNotRegex', ('foo', 'foo'), + ["^Regex matched:", + "^oops$", + "^Regex matched:", + "^Regex matched: (.*) : oops$"]) + def assertMessagesCM(self, methodName, args, func, errors): """ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -786,6 +786,7 @@ Dave Kuhlman Jon Kuhn Toshio Kuratomi +Ilia Kurenkov Vladimir Kushnir Erno Kuusela Ross Lagerwall diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Library ------- +- Issue #20362: Honour TestCase.longMessage correctly in assertRegex. + Patch from Ilia Kurenkov. + - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 20 05:38:57 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Aug 2015 03:38:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_remove_tabs_fr?= =?utf-8?q?om_ceval=2Ec_=28closes_=2324895=29?= Message-ID: <20150820033857.21654.58119@psf.io> https://hg.python.org/cpython/rev/ea2f6fd04307 changeset: 97462:ea2f6fd04307 branch: 2.7 parent: 97439:9ad330a9d785 user: Benjamin Peterson date: Wed Aug 19 20:38:39 2015 -0700 summary: remove tabs from ceval.c (closes #24895) files: Python/ceval.c | 346 ++++++++++++++++++------------------ 1 files changed, 173 insertions(+), 173 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -709,73 +709,73 @@ /* This macro is used when several opcodes defer to the same implementation (e.g. SETUP_LOOP, SETUP_FINALLY) */ #define TARGET_WITH_IMPL(op, impl) \ - TARGET_##op: \ - opcode = op; \ - oparg = NEXTARG(); \ - case op: \ - goto impl; \ + TARGET_##op: \ + opcode = op; \ + oparg = NEXTARG(); \ + case op: \ + goto impl; \ #define TARGET_WITH_IMPL_NOARG(op, impl) \ - TARGET_##op: \ - opcode = op; \ - case op: \ - goto impl; \ + TARGET_##op: \ + opcode = op; \ + case op: \ + goto impl; \ #define TARGET_NOARG(op) \ - TARGET_##op: \ - opcode = op; \ - case op:\ + TARGET_##op: \ + opcode = op; \ + case op:\ #define TARGET(op) \ - TARGET_##op: \ - opcode = op; \ - oparg = NEXTARG(); \ - case op:\ + TARGET_##op: \ + opcode = op; \ + oparg = NEXTARG(); \ + case op:\ #define DISPATCH() \ - { \ - int _tick = _Py_Ticker - 1; \ - _Py_Ticker = _tick; \ - if (_tick >= 0) { \ - FAST_DISPATCH(); \ - } \ - continue; \ - } + { \ + int _tick = _Py_Ticker - 1; \ + _Py_Ticker = _tick; \ + if (_tick >= 0) { \ + FAST_DISPATCH(); \ + } \ + continue; \ + } #ifdef LLTRACE #define FAST_DISPATCH() \ - { \ - if (!lltrace && !_Py_TracingPossible) { \ - f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ - } \ - goto fast_next_opcode; \ - } + { \ + if (!lltrace && !_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode; \ + } #else #define FAST_DISPATCH() { \ - if (!_Py_TracingPossible) { \ - f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ - } \ - goto fast_next_opcode;\ + if (!_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode;\ } #endif #else #define TARGET(op) \ - case op: + case op: #define TARGET_WITH_IMPL(op, impl) \ - /* silence compiler warnings about `impl` unused */ \ - if (0) goto impl; \ - case op:\ + /* silence compiler warnings about `impl` unused */ \ + if (0) goto impl; \ + case op:\ #define TARGET_NOARG(op) \ - case op:\ + case op:\ #define TARGET_WITH_IMPL_NOARG(op, impl) \ - if (0) goto impl; \ - case op:\ + if (0) goto impl; \ + case op:\ #define DISPATCH() continue #define FAST_DISPATCH() goto fast_next_opcode @@ -1206,9 +1206,9 @@ /* case STOP_CODE: this is an error! */ TARGET_NOARG(NOP) - { - FAST_DISPATCH(); - } + { + FAST_DISPATCH(); + } TARGET(LOAD_FAST) { @@ -1216,7 +1216,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - FAST_DISPATCH(); + FAST_DISPATCH(); } format_exc_check_arg(PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, @@ -1229,7 +1229,7 @@ x = GETITEM(consts, oparg); Py_INCREF(x); PUSH(x); - FAST_DISPATCH(); + FAST_DISPATCH(); } PREDICTED_WITH_ARG(STORE_FAST); @@ -1237,14 +1237,14 @@ { v = POP(); SETLOCAL(oparg, v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(POP_TOP) { v = POP(); Py_DECREF(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(ROT_TWO) @@ -1253,7 +1253,7 @@ w = SECOND(); SET_TOP(w); SET_SECOND(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(ROT_THREE) @@ -1264,11 +1264,11 @@ SET_TOP(w); SET_SECOND(x); SET_THIRD(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(ROT_FOUR) - { + { u = TOP(); v = SECOND(); w = THIRD(); @@ -1278,7 +1278,7 @@ SET_THIRD(x); SET_FOURTH(u); FAST_DISPATCH(); - } + } TARGET_NOARG(DUP_TOP) @@ -1286,7 +1286,7 @@ v = TOP(); Py_INCREF(v); PUSH(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } @@ -1300,7 +1300,7 @@ STACKADJ(2); SET_TOP(x); SET_SECOND(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } else if (oparg == 3) { x = TOP(); Py_INCREF(x); @@ -1312,7 +1312,7 @@ SET_TOP(x); SET_SECOND(w); SET_THIRD(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } Py_FatalError("invalid argument to DUP_TOPX" " (bytecode corruption?)"); @@ -1326,7 +1326,7 @@ x = PyNumber_Positive(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1336,7 +1336,7 @@ x = PyNumber_Negative(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1348,13 +1348,13 @@ if (err == 0) { Py_INCREF(Py_True); SET_TOP(Py_True); - DISPATCH(); + DISPATCH(); } else if (err > 0) { Py_INCREF(Py_False); SET_TOP(Py_False); err = 0; - DISPATCH(); + DISPATCH(); } STACKADJ(-1); break; @@ -1366,7 +1366,7 @@ x = PyObject_Repr(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1376,7 +1376,7 @@ x = PyNumber_Invert(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1388,7 +1388,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1400,7 +1400,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if(x!=NULL) DISPATCH(); + if(x!=NULL) DISPATCH(); break; } @@ -1413,7 +1413,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } } @@ -1426,7 +1426,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1438,7 +1438,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1453,7 +1453,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1487,7 +1487,7 @@ skip_decref_vx: Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1514,7 +1514,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1540,7 +1540,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1552,7 +1552,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1564,7 +1564,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1576,7 +1576,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1588,7 +1588,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1600,7 +1600,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1612,7 +1612,7 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - DISPATCH(); + DISPATCH(); } break; } @@ -1625,7 +1625,7 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - DISPATCH(); + DISPATCH(); } break; } @@ -1638,7 +1638,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1650,7 +1650,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1663,7 +1663,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } } @@ -1677,7 +1677,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1689,7 +1689,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1701,7 +1701,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1733,7 +1733,7 @@ skip_decref_v: Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1758,7 +1758,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1770,7 +1770,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1782,7 +1782,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1794,7 +1794,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1806,7 +1806,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1818,7 +1818,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1826,10 +1826,10 @@ TARGET_WITH_IMPL_NOARG(SLICE, _slice) TARGET_WITH_IMPL_NOARG(SLICE_1, _slice) - TARGET_WITH_IMPL_NOARG(SLICE_2, _slice) - TARGET_WITH_IMPL_NOARG(SLICE_3, _slice) - _slice: - { + TARGET_WITH_IMPL_NOARG(SLICE_2, _slice) + TARGET_WITH_IMPL_NOARG(SLICE_3, _slice) + _slice: + { if ((opcode-SLICE) & 2) w = POP(); else @@ -1844,17 +1844,17 @@ Py_XDECREF(v); Py_XDECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; - } + } TARGET_WITH_IMPL_NOARG(STORE_SLICE, _store_slice) TARGET_WITH_IMPL_NOARG(STORE_SLICE_1, _store_slice) - TARGET_WITH_IMPL_NOARG(STORE_SLICE_2, _store_slice) - TARGET_WITH_IMPL_NOARG(STORE_SLICE_3, _store_slice) - _store_slice: - { + TARGET_WITH_IMPL_NOARG(STORE_SLICE_2, _store_slice) + TARGET_WITH_IMPL_NOARG(STORE_SLICE_3, _store_slice) + _store_slice: + { if ((opcode-STORE_SLICE) & 2) w = POP(); else @@ -1870,17 +1870,17 @@ Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; - } + } TARGET_WITH_IMPL_NOARG(DELETE_SLICE, _delete_slice) TARGET_WITH_IMPL_NOARG(DELETE_SLICE_1, _delete_slice) - TARGET_WITH_IMPL_NOARG(DELETE_SLICE_2, _delete_slice) - TARGET_WITH_IMPL_NOARG(DELETE_SLICE_3, _delete_slice) - _delete_slice: - { + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_2, _delete_slice) + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_3, _delete_slice) + _delete_slice: + { if ((opcode-DELETE_SLICE) & 2) w = POP(); else @@ -1895,9 +1895,9 @@ Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; - } + } TARGET_NOARG(STORE_SUBSCR) { @@ -1910,7 +1910,7 @@ Py_DECREF(u); Py_DECREF(v); Py_DECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -1923,7 +1923,7 @@ err = PyObject_DelItem(v, w); Py_DECREF(v); Py_DECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2006,7 +2006,7 @@ Py_DECREF(v); Py_XDECREF(stream); stream = NULL; - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2018,8 +2018,8 @@ TARGET_NOARG(PRINT_NEWLINE) { - if (stream == NULL || stream == Py_None) - { + if (stream == NULL || stream == Py_None) + { w = PySys_GetObject("stdout"); if (w == NULL) { PyErr_SetString(PyExc_RuntimeError, @@ -2046,7 +2046,7 @@ #endif TARGET(RAISE_VARARGS) - { + { u = v = w = NULL; switch (oparg) { case 3: @@ -2067,15 +2067,15 @@ break; } break; - } + } TARGET_NOARG(LOAD_LOCALS) { - if ((x = f->f_locals) != NULL) - { + if ((x = f->f_locals) != NULL) + { Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } PyErr_SetString(PyExc_SystemError, "no locals"); break; @@ -2120,7 +2120,7 @@ Py_DECREF(v); } } - DISPATCH(); + DISPATCH(); } PREDICTED(END_FINALLY); @@ -2175,7 +2175,7 @@ else err = PyObject_SetItem(x, w, v); Py_DECREF(v); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } t = PyObject_Repr(w); @@ -2222,7 +2222,7 @@ PUSH(w); } Py_DECREF(v); - DISPATCH(); + DISPATCH(); } else if (PyList_CheckExact(v) && PyList_GET_SIZE(v) == oparg) { PyObject **items = \ @@ -2253,7 +2253,7 @@ err = PyObject_SetAttr(v, w, u); /* v.w = u */ Py_DECREF(v); Py_DECREF(u); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2274,7 +2274,7 @@ v = POP(); err = PyDict_SetItem(f->f_globals, w, v); Py_DECREF(v); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2328,7 +2328,7 @@ Py_INCREF(x); } PUSH(x); - DISPATCH(); + DISPATCH(); } TARGET(LOAD_GLOBAL) @@ -2352,7 +2352,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } d = (PyDictObject *)(f->f_builtins); e = d->ma_lookup(d, w, hash); @@ -2364,7 +2364,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } goto load_global_error; } @@ -2383,7 +2383,7 @@ } Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } TARGET(DELETE_FAST) @@ -2391,7 +2391,7 @@ x = GETLOCAL(oparg); if (x != NULL) { SETLOCAL(oparg, NULL); - DISPATCH(); + DISPATCH(); } format_exc_check_arg( PyExc_UnboundLocalError, @@ -2406,7 +2406,7 @@ x = freevars[oparg]; Py_INCREF(x); PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2416,7 +2416,7 @@ w = PyCell_Get(x); if (w != NULL) { PUSH(w); - DISPATCH(); + DISPATCH(); } err = -1; /* Don't stomp existing exception */ @@ -2444,7 +2444,7 @@ x = freevars[oparg]; PyCell_Set(x, w); Py_DECREF(w); - DISPATCH(); + DISPATCH(); } TARGET(BUILD_TUPLE) @@ -2456,7 +2456,7 @@ PyTuple_SET_ITEM(x, oparg, w); } PUSH(x); - DISPATCH(); + DISPATCH(); } break; } @@ -2470,7 +2470,7 @@ PyList_SET_ITEM(x, oparg, w); } PUSH(x); - DISPATCH(); + DISPATCH(); } break; } @@ -2490,7 +2490,7 @@ break; } PUSH(x); - DISPATCH(); + DISPATCH(); } break; } @@ -2499,7 +2499,7 @@ { x = _PyDict_NewPresized((Py_ssize_t)oparg); PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2513,7 +2513,7 @@ err = PyDict_SetItem(v, w, u); /* v[w] = u */ Py_DECREF(u); Py_DECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2529,7 +2529,7 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - DISPATCH(); + DISPATCH(); } break; } @@ -2541,7 +2541,7 @@ x = PyObject_GetAttr(v, w); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2579,7 +2579,7 @@ if (x == NULL) break; PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); - DISPATCH(); + DISPATCH(); } TARGET(IMPORT_NAME) @@ -2624,7 +2624,7 @@ READ_TIMESTAMP(intr1); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2642,7 +2642,7 @@ READ_TIMESTAMP(intr1); PyFrame_LocalsToFast(f, 0); Py_DECREF(v); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2654,14 +2654,14 @@ x = import_from(v, w); READ_TIMESTAMP(intr1); PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } TARGET(JUMP_FORWARD) { JUMPBY(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); @@ -2670,12 +2670,12 @@ w = POP(); if (w == Py_True) { Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_False) { Py_DECREF(w); JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); Py_DECREF(w); @@ -2685,7 +2685,7 @@ JUMPTO(oparg); else break; - DISPATCH(); + DISPATCH(); } PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); @@ -2694,12 +2694,12 @@ w = POP(); if (w == Py_False) { Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_True) { Py_DECREF(w); JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); Py_DECREF(w); @@ -2711,7 +2711,7 @@ ; else break; - DISPATCH(); + DISPATCH(); } TARGET(JUMP_IF_FALSE_OR_POP) @@ -2720,11 +2720,11 @@ if (w == Py_True) { STACKADJ(-1); Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_False) { JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); if (err > 0) { @@ -2736,7 +2736,7 @@ JUMPTO(oparg); else break; - DISPATCH(); + DISPATCH(); } TARGET(JUMP_IF_TRUE_OR_POP) @@ -2745,11 +2745,11 @@ if (w == Py_False) { STACKADJ(-1); Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_True) { JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); if (err > 0) { @@ -2762,7 +2762,7 @@ } else break; - DISPATCH(); + DISPATCH(); } PREDICTED_WITH_ARG(JUMP_ABSOLUTE); @@ -2779,7 +2779,7 @@ */ goto fast_next_opcode; #else - DISPATCH(); + DISPATCH(); #endif } @@ -2792,7 +2792,7 @@ if (x != NULL) { SET_TOP(x); PREDICT(FOR_ITER); - DISPATCH(); + DISPATCH(); } STACKADJ(-1); break; @@ -2808,7 +2808,7 @@ PUSH(x); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); - DISPATCH(); + DISPATCH(); } if (PyErr_Occurred()) { if (!PyErr_ExceptionMatches( @@ -2820,7 +2820,7 @@ x = v = POP(); Py_DECREF(v); JUMPBY(oparg); - DISPATCH(); + DISPATCH(); } TARGET_NOARG(BREAK_LOOP) @@ -2842,9 +2842,9 @@ TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) - TARGET(SETUP_FINALLY) - _setup_finally: - { + TARGET(SETUP_FINALLY) + _setup_finally: + { /* NOTE: If you add any new block-setup opcodes that are not try/except/finally handlers, you may need to update the PyGen_NeedsFinalizing() function. @@ -2852,8 +2852,8 @@ PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL()); - DISPATCH(); - } + DISPATCH(); + } @@ -2884,8 +2884,8 @@ STACK_LEVEL()); PUSH(x); - DISPATCH(); - } + DISPATCH(); + } } TARGET_NOARG(WITH_CLEANUP) @@ -2988,14 +2988,14 @@ #endif stack_pointer = sp; PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw) TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw) - TARGET(CALL_FUNCTION_VAR_KW) - _call_function_var_kw: + TARGET(CALL_FUNCTION_VAR_KW) + _call_function_var_kw: { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; @@ -3033,7 +3033,7 @@ Py_DECREF(w); } PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -3110,7 +3110,7 @@ Py_DECREF(v); Py_XDECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Thu Aug 20 17:14:43 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Thu, 20 Aug 2015 15:14:43 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-20 Message-ID: Results for project python_default-nightly, build date 2015-08-20 09:02:22 commit: 977e60f597de5458e09f6e3443950ed11703b1ad revision date: 2015-08-20 02:13:38 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.19108% 1.12735% 7.47953% :-( pybench sec 0.14169% -0.05207% -2.40216% :-( regex_v8 sec 2.83562% 0.21258% -3.12522% :-| nbody sec 0.17297% -0.14527% -1.36068% :-| json_dump_v2 sec 0.21123% -0.38883% -0.37480% :-| normal_startup sec 0.75858% 0.24845% 0.31371% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Fri Aug 21 02:02:43 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 00:02:43 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP-498_updates=3A_specify_st?= =?utf-8?q?r=2Einterpolate=28=29_and_beef_up_some_of_the_discussion?= Message-ID: <20150821000243.22346.12255@psf.io> https://hg.python.org/peps/rev/cfb1f33513f7 changeset: 5958:cfb1f33513f7 user: Eric V. Smith date: Thu Aug 20 20:02:45 2015 -0400 summary: PEP-498 updates: specify str.interpolate() and beef up some of the discussion text. Still needs work on the XXX marked sections. files: pep-0498.txt | 120 ++++++++++++++++++++++++++++++-------- 1 files changed, 95 insertions(+), 25 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -41,6 +41,9 @@ >>> f'He said his name is {name!r}.' "He said his name is 'Fred'." +This PEP proposes a new method on the str type: str.interpolate. This +method will be used to implement f-strings. + A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to support a subset of Python expressions, and did not support the type-specific string formatting (the __format__ method) which was @@ -139,6 +142,11 @@ >>> outer(42)() 'x=42' +In addition, using locals() or globals() introduces an information +leak. A called routine that has access to the callers locals() or +globals() has access to far more information than needed to do the +string interpolation. + Guido stated [#]_ that any solution to better string interpolation would not use locals() or globals(). @@ -185,21 +193,34 @@ brackets, or braces. The exception is that the '!=' operator is special cased. +str.interpolate() +----------------- + +str.interpolate will be a new method. It takes one argument: a mapping +of field names to values. This method is the same as str.format_map() +[#]_, with one difference: it does not interpret the field_name [#]_ +in any way. The field name is only used to look up the replacement +value in the supplied mapping object. Like str.format() and +str.format_map(), it does interpret and apply the optional conversion +character and format specifier. Thus, a field name may not contain the +characters ':' or '}', nor the strings '!s' and '!r'. + Code equivalence ---------------- -The exact code that is executed when converting expressions to strings -is unspecified by this PEP. However, it is specified that once the -expression is evaluated, the result's __format__() method will be -called with the given format specifier. +An f-string is evaluated at run time as a call to str.interpolate(). For example, this code:: f'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi' -May be evaluated as:: +Will be be evaluated as:: - ''.join(['abc', expr1.__format__('spec1'), repr(expr2).__format__('spec2'), 'def', str(expr3).__format__(''), 'ghi']) + 'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi'.interpolate({'expr1': expr1, 'expr2': expr2, 'expr3': expr3}) + +Note that the string on which interpolate() is being called is +identical to the value of the f-string. + Expression evaluation --------------------- @@ -258,10 +279,11 @@ 'ab10cstr< hi >de' -While the exact code that is executed when evaluating this f-string is -not specified, one possible strategy is to evaluate:: +While the exact method of this runtime concatenation is unspecified, +the above code might evaluate to:: - ''.join(['ab', x.__format__(''), 'c', 'str<', y.__format__('^4'), '>', 'de']) + + ''.join(['ab', '{x}'.interpolate({'x': x}), 'c', 'str<', 'str<{y:^4}>'.interpolate({'y': y}), 'de']) Error handling -------------- @@ -310,24 +332,20 @@ File "", line 2, in ValueError: Sign not allowed in string format specifier -Leading whitespace in expressions is skipped --------------------------------------------- +Leading and trailing whitespace in expressions is skipped +--------------------------------------------------------- -Because expressions may begin with a left brace ('{'), there is a -problem when parsing such expressions. For example:: +For ease of readability, leading and trailing whitespace in +expressions is ignored. However, this does not affect the string or +keys passed to str.interpolate(). - >>> f'{{k:v for k, v in [(1, 2), (3, 4)]}}' - '{k:v for k, v in [(1, 2), (3, 4)]}' + >>> x = 100 + >>> f'x = { x }' + 'x = 100' -In this case, the doubled left braces and doubled right braces are -interpreted as single braces, and the string becomes just a normal -string literal. There is no expression evaluation being performed. +This would be evaluated as:: -To allow for expressions to begin with a left brace, whitespace -characters at the beginning of an expression are skipped:: - - >>> f'{ {k:v for k, v in [(1, 2), (3, 4)]}}' - '{1: 2, 3: 4}' + 'x = { x }'.interpolate({' x ': 100}) Discussion ========== @@ -337,14 +355,15 @@ - Whether to allow full Python expressions. - How to designate f-strings, and how to specify the location of expressions in them. - - How to concatenate adjacent strings and f-strings. XXX: more on the above issues. Similar support in other languages ---------------------------------- -XXX: Placeholder. +Wikipedia has a good discussion of string interpolation in other +programming languages [#]_. This feature is implemented in many +languages, with a variety of syntaxes and restrictions. Differences between f-string and str.format expressions ------------------------------------------------------- @@ -377,6 +396,25 @@ See [#]_ for a further discussion. It was this observation that led to full Python expressions being supported in f-strings. +Triple-quoted f-strings +----------------------- + +Triple quoted f-strings are allowed. These strings are parsed just as +normal triple-quoted strings are. After parsing, the normal f-string +logic is applied, and str.interpolate() is called. + +Raw f-strings +------------- + +Raw and f-strings may be combined. For example they could be used to +build up regular expressions:: + + >>> header = 'Subject' + >>> fr'{header}:\s+' + 'Subject:\\s+' + +In addition, raw f-strings may be combined with triple-quoted strings. + No binary f-strings ------------------- @@ -385,6 +423,8 @@ object's __format__() method may return Unicode data that is not compatible with a bytes string. +#XXX: maybe allow this, but encode the output as ascii? + !s and !r are redundant ----------------------- @@ -421,6 +461,27 @@ >>> f'{(lambda x: x*2)(3)}' '6' +Future extensions: +================== + +XXX: By using another leading character (say, 'i'), we could extend +this proposal to cover internationalization and localization. The idea +is that the string would be passed to some lookup function before +.interpolate() is called on it: + + >>> name = 'Eric' + >>> fi'Name: {name}' + +Could be translated as:: + + gettext.gettext('Name: {name}').interpolate({'name': name}) + +If gettext.gettext() returned '{name} es mi nombre', then the +resulting string would be 'Eric es mi nombre'. + +Any such internationalization work will be specified in an additional +PEP. + References ========== @@ -445,6 +506,15 @@ .. [#] Avoid locals() and globals() (https://mail.python.org/pipermail/python-ideas/2015-July/034701.html) +.. [#] str.format_map() documentation + (https://docs.python.org/3/library/stdtypes.html#str.format_map) + +.. [#] Format string syntax + (https://docs.python.org/3/library/string.html#format-string-syntax) + +.. [#] Wikipedia article on string interpolation + (https://en.wikipedia.org/wiki/String_interpolation) + .. [#] Start of python-ideas discussion (https://mail.python.org/pipermail/python-ideas/2015-July/034657.html) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 02:13:37 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 00:13:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Also_support_!a=2C_since_it_i?= =?utf-8?q?s_in_Python_3=2E?= Message-ID: <20150821001336.21437.90956@psf.io> https://hg.python.org/peps/rev/bf55b97b6fa3 changeset: 5959:bf55b97b6fa3 user: Eric V. Smith date: Thu Aug 20 20:13:37 2015 -0400 summary: Also support !a, since it is in Python 3. files: pep-0498.txt | 52 +++++++++++++++++++++------------------ 1 files changed, 28 insertions(+), 24 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -41,8 +41,8 @@ >>> f'He said his name is {name!r}.' "He said his name is 'Fred'." -This PEP proposes a new method on the str type: str.interpolate. This -method will be used to implement f-strings. +This PEP proposes a new method on the str type: +str.interpolate(). This method will be used to implement f-strings. A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to support a subset of Python expressions, and did not support the @@ -169,12 +169,13 @@ start of an expression. Following the expression, an optional type conversion may be -specified. The allowed conversions are '!s' or '!r'. These are +specified. The allowed conversions are '!s', '!r', or '!a'. These are treated the same as in str.format: '!s' calls str() on the expression, -and '!r' calls repr() on the expression. These conversions are applied -before the call to __format__. The only reason to use '!s' is if you -want to specify a format specifier that applies to str, not to the -type of the expression. +'!r' calls repr() on the expression, and '!a' calls ascii() on the +expression. These conversions are applied before the call to +__format__. The only reason to use '!s' is if you want to specify a +format specifier that applies to str, not to the type of the +expression. Similar to str.format, optional format specifiers maybe be included inside the f-string, separated from the expression (or the type @@ -183,7 +184,7 @@ So, an f-string looks like:: - f ' { } text ... ' + f ' { } text ... ' The resulting expression's __format__ method is called with the format specifier. The resulting value is used when building the value of the @@ -196,14 +197,15 @@ str.interpolate() ----------------- -str.interpolate will be a new method. It takes one argument: a mapping -of field names to values. This method is the same as str.format_map() -[#]_, with one difference: it does not interpret the field_name [#]_ -in any way. The field name is only used to look up the replacement -value in the supplied mapping object. Like str.format() and -str.format_map(), it does interpret and apply the optional conversion -character and format specifier. Thus, a field name may not contain the -characters ':' or '}', nor the strings '!s' and '!r'. +str.interpolate() will be a new method. It takes one argument: a +mapping of field names to values. This method is the same as +str.format_map() [#]_, with one difference: it does not interpret the +field_name [#]_ in any way. The field name is only used to look up the +replacement value in the supplied mapping object. Like str.format() +and str.format_map(), it does interpret and apply the optional +conversion character and format specifier. Thus, a field name may not +contain the characters ':' or '}', nor the strings '!s', '!r', or +'!a'. Code equivalence ---------------- @@ -425,11 +427,11 @@ #XXX: maybe allow this, but encode the output as ascii? -!s and !r are redundant ------------------------ +!s, !r, and !s are redundant +---------------------------- -The !s and !r are not strictly required. Because arbitrary expressions -are allowed inside the f-strings, this code:: +The !s, !r, and !a are not strictly required. Because arbitrary +expressions are allowed inside the f-strings, this code:: >>> a = 'some string' >>> f'{a!r}' @@ -440,11 +442,13 @@ >>> f'{repr(a)}' "'some string'" -Similarly, !s can be replaced by calls to str(). +Similarly, !s can be replaced by calls to str() and !a by calls to +ascii(). -However, !s and !r are supported by this PEP in order to minimize the -differences with str.format(). !s and !r are required in str.format() -because it does not allow the execution of arbitrary expressions. +However, !s, !r, and !a are supported by this PEP in order to minimize +the differences with str.format(). !s, !r, and !a are required in +str.format() because it does not allow the execution of arbitrary +expressions. Lambdas inside expressions -------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 02:55:52 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 00:55:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Straightened_out_footnotes=2E?= Message-ID: <20150821005552.22330.74493@psf.io> https://hg.python.org/peps/rev/194e513b553e changeset: 5960:194e513b553e user: Eric V. Smith date: Thu Aug 20 20:27:23 2015 -0400 summary: Straightened out footnotes. files: pep-0498.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -516,12 +516,12 @@ .. [#] Format string syntax (https://docs.python.org/3/library/string.html#format-string-syntax) +.. [#] Start of python-ideas discussion + (https://mail.python.org/pipermail/python-ideas/2015-July/034657.html) + .. [#] Wikipedia article on string interpolation (https://en.wikipedia.org/wiki/String_interpolation) -.. [#] Start of python-ideas discussion - (https://mail.python.org/pipermail/python-ideas/2015-July/034657.html) - .. [#] Differences in str.format() and f-string expressions (https://mail.python.org/pipermail/python-ideas/2015-July/034726.html) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 02:55:52 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 00:55:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Clean_up_usage_of_format=5Fsp?= =?utf-8?q?ec_and_field=5Fname=2E_Add_additional_verbiage_about?= Message-ID: <20150821005552.53597.24848@psf.io> https://hg.python.org/peps/rev/19465f3c9f4f changeset: 5961:19465f3c9f4f user: Eric V. Smith date: Thu Aug 20 20:55:54 2015 -0400 summary: Clean up usage of format_spec and field_name. Add additional verbiage about i18n and concatenating adjacent f-strings. files: pep-0498.txt | 35 +++++++++++++++++++++++++++-------- 1 files changed, 27 insertions(+), 8 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -82,7 +82,9 @@ %-formatting. In particular, it uses normal function call syntax (and therefor supports mutliple parameters) and it is extensible through the __format__() method on the object being converted to a string. See -PEP-3101 for a detailed rationale. +PEP-3101 for a detailed rationale. This PEP reuses much of the +str.format() syntax and machinery, in order to provide continuity with +an existing Python string formatting mechanism. However, str.format() is not without its issues. Chief among them are its verbosity. For example, the text 'value' is repeated here:: @@ -197,13 +199,13 @@ str.interpolate() ----------------- -str.interpolate() will be a new method. It takes one argument: a -mapping of field names to values. This method is the same as +str.interpolate(mapping) will be a new method. It takes one argument: +a mapping of field names to values. This method is the same as str.format_map() [#]_, with one difference: it does not interpret the -field_name [#]_ in any way. The field name is only used to look up the +field_name [#]_ in any way. The field_name is only used to look up the replacement value in the supplied mapping object. Like str.format() -and str.format_map(), it does interpret and apply the optional -conversion character and format specifier. Thus, a field name may not +and str.format_map(), str.interpolate() does interpret and apply the +optional conversion and format_spec. Thus, a field_name may not contain the characters ':' or '}', nor the strings '!s', '!r', or '!a'. @@ -281,12 +283,24 @@ 'ab10cstr< hi >de' -While the exact method of this runtime concatenation is unspecified, +While the exact method of this run time concatenation is unspecified, the above code might evaluate to:: ''.join(['ab', '{x}'.interpolate({'x': x}), 'c', 'str<', 'str<{y:^4}>'.interpolate({'y': y}), 'de']) +You are guaranteed, however, that there will be no compile time +combination of f-strings:: + + >>> x = 0 + >>> y = 1 + >>> f'{x}' f'{y}' + '01' + +Will result in 2 calls to str.interpolate(): once on the string '{x}', +and again on the string '{y}'. This guarantee is needed to facilitate +proposed future internationalization. + Error handling -------------- @@ -484,7 +498,12 @@ resulting string would be 'Eric es mi nombre'. Any such internationalization work will be specified in an additional -PEP. +PEP. In all likelyhood, such a PEP will need to propose one or more +additional optional parameters to str.interpolate() in order to handle +the string.Template case of "safe substitution", where the substituted +field_names are not found in the mapping argument. The choices might +be: use the field_name, use a default (possibly empty) string, or +raise an exception. References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 03:14:41 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 01:14:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Incorporate_feedback_from_Gui?= =?utf-8?q?do=2E_Still_several_more_items_to_tackle=2E?= Message-ID: <20150821011441.12123.1349@psf.io> https://hg.python.org/peps/rev/ae7fed88f7dd changeset: 5962:ae7fed88f7dd user: Eric V. Smith date: Thu Aug 20 21:14:43 2015 -0400 summary: Incorporate feedback from Guido. Still several more items to tackle. files: pep-0498.txt | 31 +++++++++++++++++++++++++++---- 1 files changed, 27 insertions(+), 4 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -251,6 +251,27 @@ >>> 'result=' + str(foo()) 'result=20' +After stripping leading and trailing whitespace (see below), the +expression is parsed with the equivalent of ast.parse(expression, +'', 'eval') [#]_. Note that this restricts the expression: it +cannot contain any newlines, for example:: + + >>> x = 0 + >>> f'''{x + ... +1}''' + File "", line 2 + +1 + ^ + SyntaxError: invalid syntax + +But note that this works, since the newline is removed from the +string, and the spaces in from of the '1' are allowed in an +expression:: + + >>> f'{x+\ + ... 1}' + '2' + Format specifiers ----------------- @@ -277,17 +298,16 @@ >>> x = 10 >>> y = 'hi' - >>> 'a' 'b' f'{x}' 'c' f'str<{y:^4}>' 'd' 'e' + >>> 'a' 'b' f'{x}' '{c}' f'str<{y:^4}>' 'd' 'e' yields the value:: - 'ab10cstr< hi >de' + 'ab10{c}str< hi >de' While the exact method of this run time concatenation is unspecified, the above code might evaluate to:: - - ''.join(['ab', '{x}'.interpolate({'x': x}), 'c', 'str<', 'str<{y:^4}>'.interpolate({'y': y}), 'de']) + ''.join(['ab', '{x}'.interpolate({'x': x}), '{c}', 'str<', 'str<{y:^4}>'.interpolate({'y': y}), 'de']) You are guaranteed, however, that there will be no compile time combination of f-strings:: @@ -535,6 +555,9 @@ .. [#] Format string syntax (https://docs.python.org/3/library/string.html#format-string-syntax) +.. [#] ast.parse() documentation + (https://docs.python.org/3/library/ast.html#ast.parse) + .. [#] Start of python-ideas discussion (https://mail.python.org/pipermail/python-ideas/2015-July/034657.html) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 03:18:49 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 01:18:49 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_some_markup=2E?= Message-ID: <20150821011849.22330.41045@psf.io> https://hg.python.org/peps/rev/d317f0245d6f changeset: 5963:d317f0245d6f user: Eric V. Smith date: Thu Aug 20 21:18:50 2015 -0400 summary: Fix some markup. files: pep-0498.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -373,7 +373,7 @@ For ease of readability, leading and trailing whitespace in expressions is ignored. However, this does not affect the string or -keys passed to str.interpolate(). +keys passed to str.interpolate():: >>> x = 100 >>> f'x = { x }' @@ -386,7 +386,7 @@ Discussion ========== -Most of the discussions on python-ideas [#]_ focused on a few issues: +Most of the discussions on python-ideas [#]_ focused on a few issues. - Whether to allow full Python expressions. - How to designate f-strings, and how to specify the location of @@ -505,7 +505,7 @@ XXX: By using another leading character (say, 'i'), we could extend this proposal to cover internationalization and localization. The idea is that the string would be passed to some lookup function before -.interpolate() is called on it: +.interpolate() is called on it:: >>> name = 'Eric' >>> fi'Name: {name}' -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 10:54:20 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 08:54:20 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_more_words_about_reject?= =?utf-8?q?ing_binary_f-strings=2E?= Message-ID: <20150821085419.113144.50091@psf.io> https://hg.python.org/peps/rev/def0d4b6bb17 changeset: 5964:def0d4b6bb17 user: Eric V. Smith date: Fri Aug 21 04:54:23 2015 -0400 summary: Added more words about rejecting binary f-strings. files: pep-0498.txt | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -459,7 +459,18 @@ object's __format__() method may return Unicode data that is not compatible with a bytes string. -#XXX: maybe allow this, but encode the output as ascii? +Binary f-strings would first require a solution for +bytes.format(). This idea has been proposed in the past, most recently +in PEP 461 [#]_. The discussions of such a feature usually suggest either + + - adding a method such as __bformat__() so an object can control how + it is converted to bytes, or + + - having bytes.format() not be as general purpose or extensible as + str.format(). + +Both of these remain as options in the future, if such functionality +is desired. !s, !r, and !s are redundant ---------------------------- @@ -567,6 +578,9 @@ .. [#] Differences in str.format() and f-string expressions (https://mail.python.org/pipermail/python-ideas/2015-July/034726.html) +.. [#] PEP 461 rejects bytes.format(), see section "Proposed variations" + (http://legacy.python.org/dev/peps/pep-0461) + Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 10:57:02 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 08:57:02 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Better_link_for_PEP_461=2E?= Message-ID: <20150821085702.96567.92266@psf.io> https://hg.python.org/peps/rev/149fac9bb11b changeset: 5965:149fac9bb11b user: Eric V. Smith date: Fri Aug 21 04:57:04 2015 -0400 summary: Better link for PEP 461. files: pep-0498.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -578,8 +578,8 @@ .. [#] Differences in str.format() and f-string expressions (https://mail.python.org/pipermail/python-ideas/2015-July/034726.html) -.. [#] PEP 461 rejects bytes.format(), see section "Proposed variations" - (http://legacy.python.org/dev/peps/pep-0461) +.. [#] PEP 461 rejects bytes.format() + (https://www.python.org/dev/peps/pep-0461/#proposed-variations) Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 11:13:36 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 09:13:36 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Improve_comparison_to_string?= =?utf-8?q?=2ETemplate_and_=25-formatting=2E?= Message-ID: <20150821091336.22348.604@psf.io> https://hg.python.org/peps/rev/249092f2e117 changeset: 5966:249092f2e117 user: Eric V. Smith date: Fri Aug 21 05:13:39 2015 -0400 summary: Improve comparison to string.Template and %-formatting. files: pep-0498.txt | 23 +++++++++++++++++++---- 1 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -86,7 +86,7 @@ str.format() syntax and machinery, in order to provide continuity with an existing Python string formatting mechanism. -However, str.format() is not without its issues. Chief among them are +However, str.format() is not without its issues. Chief among them is its verbosity. For example, the text 'value' is repeated here:: >>> value = 4 * 20 @@ -108,9 +108,24 @@ f-strings provide a concise, readable way to include expressions inside strings. -string.Template has similar shortcomings to str.format(), but also -supports fewer formatting options. In particular, it does not support -__format__. +In this sense, string.Template and %-formatting have similar +shortcomings to str.format(), but also support fewer formatting +options. In particular, they do not support __format__, so that there +is no way to control how a specific object is converted to a string, +nor can it be extended to additional types that want to control how +they are converted to strings (such as Decimal and datetime). This +example is not possible with string.Template:: + + >>> value = 1234 + >>> f'input={value:#0.6x}' + 'input=0x04d2' + +And neither %-formatting nor string.Template can control formatting +such as:: + + >>> date = datetime.date(1991, 10, 12) + >>> f'{date} was on a {date:%A}' + '1991-10-12 was on a Saturday' No use of globals() or locals() ------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 21 15:39:51 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 13:39:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_a_trivial_typo=2E?= Message-ID: <20150821133951.12117.54172@psf.io> https://hg.python.org/cpython/rev/45bb27eae8d3 changeset: 97463:45bb27eae8d3 parent: 97461:977e60f597de user: Eric V. Smith date: Fri Aug 21 09:40:38 2015 -0400 summary: Fix a trivial typo. files: Python/ast.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -511,7 +511,7 @@ /* Data structure used internally */ struct compiling { char *c_encoding; /* source encoding */ - PyArena *c_arena; /* arena for allocating memeory */ + PyArena *c_arena; /* Arena for allocating memory. */ PyObject *c_filename; /* filename */ PyObject *c_normalize; /* Normalization function from unicodedata. */ PyObject *c_normalize_args; /* Normalization argument tuple. */ -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Fri Aug 21 16:36:04 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Fri, 21 Aug 2015 14:36:04 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-21 Message-ID: Results for project python_default-nightly, build date 2015-08-21 09:01:58 commit: 977e60f597de5458e09f6e3443950ed11703b1ad revision date: 2015-08-20 02:13:38 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.19108% 1.12735% 7.47953% :-( pybench sec 0.14169% -0.05207% -2.40216% :-( regex_v8 sec 2.83562% 0.21258% -3.12522% :-| nbody sec 0.17297% -0.14527% -1.36068% :-| json_dump_v2 sec 0.21123% -0.38883% -0.37480% :-| normal_startup sec 0.75858% 0.24845% 0.31371% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sat Aug 22 00:35:03 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 22:35:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Flushed_out_more_text=2E_Othe?= =?utf-8?q?r_than_removing_!s=2C_!r=2C_and_!a=2C_I_think_I_am_mostly?= Message-ID: <20150821223503.29362.68700@psf.io> https://hg.python.org/peps/rev/9ecd060e9d3b changeset: 5967:9ecd060e9d3b user: Eric V. Smith date: Fri Aug 21 18:35:55 2015 -0400 summary: Flushed out more text. Other than removing !s, !r, and !a, I think I am mostly done. files: pep-0498.txt | 157 +++++++++++++++++++++++++++++++------- 1 files changed, 126 insertions(+), 31 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -25,12 +25,12 @@ This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms. -f-strings provide a way to combine string literals with Python -expressions, using a minimal syntax. It should be noted that an -f-string is really an expression evaluated at run time, not a constant -value. An f-string is a string, prefixed with 'f', that contains -expressions inside braces. The expressions are replaced with their -values. Some examples are:: +f-strings provide a way to embed expressions inside string literals, +using a minimal syntax. It should be noted that an f-string is really +an expression evaluated at run time, not a constant value. In Python +source code, an f-string is a literal string, prefixed with 'f', that +contains expressions inside braces. The expressions are replaced with +their values. Some examples are:: >>> import datetime >>> name = 'Fred' @@ -110,11 +110,11 @@ In this sense, string.Template and %-formatting have similar shortcomings to str.format(), but also support fewer formatting -options. In particular, they do not support __format__, so that there -is no way to control how a specific object is converted to a string, -nor can it be extended to additional types that want to control how -they are converted to strings (such as Decimal and datetime). This -example is not possible with string.Template:: +options. In particular, they do not support the __format__ protocol, +so that there is no way to control how a specific object is converted +to a string, nor can it be extended to additional types that want to +control how they are converted to strings (such as Decimal and +datetime). This example is not possible with string.Template:: >>> value = 1234 >>> f'input={value:#0.6x}' @@ -164,6 +164,11 @@ globals() has access to far more information than needed to do the string interpolation. +If locals() and globals() were used, and if a future extension to this +PEP would add an internationalization layer before str.interpolate() +is called, a malicious translator could get access to additional +variables in the callers context. + Guido stated [#]_ that any solution to better string interpolation would not use locals() or globals(). @@ -214,20 +219,44 @@ str.interpolate() ----------------- -str.interpolate(mapping) will be a new method. It takes one argument: -a mapping of field names to values. This method is the same as -str.format_map() [#]_, with one difference: it does not interpret the -field_name [#]_ in any way. The field_name is only used to look up the -replacement value in the supplied mapping object. Like str.format() -and str.format_map(), str.interpolate() does interpret and apply the -optional conversion and format_spec. Thus, a field_name may not -contain the characters ':' or '}', nor the strings '!s', '!r', or -'!a'. +str.interpolate(mapping) will be a new method on the str type. It +takes one argument: a mapping of field names to values. This method is +the same as str.format_map() [#]_, with one difference: it does not +interpret the field_name [#]_ in any way. The field_name is only used +to look up the replacement value in the supplied mapping object. Like +str.format() and str.format_map(), str.interpolate() does interpret +and apply the optional conversion and format_spec. Thus, a field_name +may not contain the characters ':' or '}', nor the strings '!s', '!r', +or '!a'. + +Examples:: + + >>> name = 'Guido' + >>> 'name={name}'.interpolate({'name': name}) + 'name=Guido' + + >>> '{date} was on a {date:%A}. It was {weather}.'.interpolate({'weather': 'sunny', 'date': datetime.date(1991, 10, 12)}) + '1991-10-12 was on a Saturday. It was sunny.' + +Like str.format_map(), only the field_name portion inside braces is +used to look up values in the mapping. The format_spec is not used as +part of this lookup. Thus:: + + >>> 'name={name:10}'.interpolate({'name': name}) + 'name=Guido ' + +But:: + + >>> 'name={name:10}'.interpolate({'name:10': name}) + 'name=Guido ' + Traceback (most recent call last): + File "", line 1, in + KeyError: 'name' Code equivalence ---------------- -An f-string is evaluated at run time as a call to str.interpolate(). +An f-string is evaluated at run time using a call to str.interpolate(). For example, this code:: @@ -401,13 +430,77 @@ Discussion ========== -Most of the discussions on python-ideas [#]_ focused on a few issues. +python-ideas discussion +----------------------- +Most of the discussions on python-ideas [#]_ focused on three issues: + + - How to denote f-strings, + - How to specify the location of expressions in f-strings, and - Whether to allow full Python expressions. - - How to designate f-strings, and how to specify the location of - expressions in them. -XXX: more on the above issues. +How to denote f-strings +*********************** + +Because the compiler must be involved in evaluating the expressions +contained in the interpolated strings, there must be some way to +denote to the compiler which strings should be evaluated. This PEP +chose a leading 'f' character preceeding the string literal. This is +similar to how 'b' and 'r' prefixes change the meaning of the string +itself, at compile time. Other prefixes were suggested, such as 'i'. No +option seemed better than the other, so 'f' was chosen. + +Another option was to support special functions, known to the +compiler, such as Format(). This seems like too much magic for Python: +not only is there a chance for collision with existing identifiers, +the PEP author feels that it's better to signify the magic with a +string prefix character. + +How to specify the location of expressions in f-strings +******************************************************* + +This PEP supports the same syntax as str.format() for distinguishing +replacement text inside strings: expressions are contained inside +braces. There were other options suggested, such as string.Template's +$identifier or ${expression}. + +While $identifier is no doubt more familiar to shell scripters and +users of some other languages, in Python str.format() is heavily +used. A quick search of Python's standard library shows only a handful +of uses of string.Template, but over 1000 uses of str.format(). + +Another proposed alternative was to have the substituted text between +\{ and } or between \{ and \}. While this syntax would probably be +desirable if all string literals were to support interpolation, this +PEP only supports strings that are already marked with the leading +'f'. As such, the PEP is using unadorned braces to denoted substituted +text, in order to leverage end user familiarity with str.format(). + +Supporting full Python expressions +********************************** + +Many people on the python-ideas discussion wanted support for either +only single identifiers, or a limited subset of Python expressions +(such as the subset supported by str.format()). This PEP supports full +Python expressions inside the braces. Without full expressions, some +desirable usage would be forbidden:: + + >>> f'Column={col_idx+1}' + >>> f'number of items: {len(items)}' + +would become:: + + >>> col_number = col_idx+1 + >>> f'Column={col_number}' + >>> n_items = len(items) + >>> f'number of items: {n_items}' + +While it's true that very ugly expressions could be included in the +f-strings, this PEP takes the position that such uses should be +addressed in a linter or code review:: + + >>> f'mapping is { {a:b for (a, b) in ((1, 2), (3, 4))}}' + 'mapping is {1: 2, 3: 4}' Similar support in other languages ---------------------------------- @@ -528,13 +621,13 @@ Future extensions: ================== -XXX: By using another leading character (say, 'i'), we could extend -this proposal to cover internationalization and localization. The idea -is that the string would be passed to some lookup function before +By using another leading character (say, 'i'), we could extend this +proposal to cover internationalization and localization. The idea is +that the string would be passed to some lookup function before .interpolate() is called on it:: >>> name = 'Eric' - >>> fi'Name: {name}' + >>> i'Name: {name}' Could be translated as:: @@ -551,8 +644,10 @@ be: use the field_name, use a default (possibly empty) string, or raise an exception. -References -========== +There would obviously need to be some way to specify to the compiler +what lookup function would be called. + +References ========== .. [#] %-formatting (https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 00:38:05 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 21 Aug 2015 22:38:05 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Restored_accidentally_deleted?= =?utf-8?q?_newline=2E?= Message-ID: <20150821223805.22332.27992@psf.io> https://hg.python.org/peps/rev/9ec916c0b2e8 changeset: 5968:9ec916c0b2e8 user: Eric V. Smith date: Fri Aug 21 18:38:38 2015 -0400 summary: Restored accidentally deleted newline. files: pep-0498.txt | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -647,7 +647,8 @@ There would obviously need to be some way to specify to the compiler what lookup function would be called. -References ========== +References +========== .. [#] %-formatting (https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 04:28:28 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 22 Aug 2015 02:28:28 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Addressed_several_?= =?utf-8?q?=28not_all_yet=29_mailing_list_commments=2E?= Message-ID: <20150822022826.76195.38422@psf.io> https://hg.python.org/peps/rev/3bf478b656e6 changeset: 5969:3bf478b656e6 user: Alexander Belopolsky date: Fri Aug 21 22:28:19 2015 -0400 summary: PEP 495: Addressed several (not all yet) mailing list commments. files: pep-0495.txt | 277 +++++++++++++++++++++++++------------- 1 files changed, 181 insertions(+), 96 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -21,15 +21,15 @@ .. sidebar:: US public service advertisement .. image:: pep-0495-daylightsavings.png - :align: right - :width: 15% + :align: center + :width: 95% Rationale ========= In the most world locations there have been and will be times when -local clocks are moved back. In those times, intervals are introduced +local clocks are moved back. [#]_ In those times, intervals are introduced in which local clocks show the same time twice in the same day. In these situations, the information displayed on a local clock (or stored in a Python datetime instance) is insufficient to identify a @@ -37,14 +37,27 @@ flag to the ``datetime`` instances that will distinguish between the two ambiguous times. +.. [#] People who live in locations observing the Daylight Saving + Time (DST) move their clocks back (usually one hour) every Fall. + + It is less common, but occasionally clocks can be moved back for + other reasons. For example, Ukraine skipped the spring-forward + transition in March 1990 and instead, moved their clocks back on + July 1, 1990, switching from Moscow Time to Eastern European Time. + In that case, standard (winter) time was in effect before and after + the transition. + + Both DST and standard time changes may result in time shifts other + than an hour. + Terminology =========== -When clocks are moved back, we say that a *fold* is created in the -fabric of time. When the clock are moved forward, a *gap* is created. -A local time that falls in the fold is called *ambiguous*. A local -time that falls in the gap is called *missing*. +When clocks are moved back, we say that a *fold* is created in time. +When the clocks are moved forward, a *gap* is created. A local time +that falls in the fold is called *ambiguous*. A local time that falls +in the gap is called *missing*. Proposal @@ -55,7 +68,7 @@ We propose adding a boolean member called ``first`` to the instances of ``datetime.time`` and ``datetime.datetime`` classes. This member -should have the value True for all instances except those that +should have the value ``True`` for all instances except those that represent the second (chronologically) moment in time in an ambiguous case. [#]_ @@ -143,6 +156,18 @@ Affected Behaviors ------------------ +What time is it? +................ + +The ``datetime.now()`` method called with no arguments, will set +``first=False`` when returning the second of the two ambiguous times +in a fold. When called with a ``tzinfo`` argument, the value of the +``first`` will be determined by the ``tzinfo.fromutc()`` +implementation. If an instance of the built-in ``datetime.timezone`` +is passed as ``tzinfo``, the returned datetime instance will always +have ``first=True``. + + Conversion from naive to aware .............................. @@ -159,16 +184,31 @@ >>> dt.replace(first=False).astimezone().strftime('%D %T %Z%z') '11/02/14 01:30:00 EST-0500' + +Conversion from POSIX seconds from EPOCH +........................................ + +The ``fromtimestamp()`` static method of ``datetime.datetime`` will +set the ``first`` attribute appropriately in the returned object. + +For example, on a system set to US/Eastern timezone:: + + >>> datetime.fromtimestamp(1414906200) + datetime.datetime(2014, 11, 2, 1, 30) + >>> datetime.fromtimestamp(1414906200 + 3600) + datetime.datetime(2014, 11, 2, 1, 30, first=False) + + Conversion to POSIX seconds from EPOCH ...................................... The ``timestamp()`` method of ``datetime.datetime`` will return different values for ``datetime.datetime`` instances that differ only by the value of their ``first`` attribute if and only if these instances represent an -ambiguous or a non-existent time. +ambiguous or a missing time. When a ``datetime.datetime`` instance ``dt`` represents an ambiguous -(repeated) time, there are two values ``s0`` and ``s1`` such that:: +time, there are two values ``s0`` and ``s1`` such that:: datetime.fromtimestamp(s0) == datetime.fromtimestamp(s1) == dt @@ -208,21 +248,6 @@ 1425796200.0 -Conversion from POSIX seconds from EPOCH -........................................ - - -The ``fromtimestamp()`` static method of ``datetime.datetime`` will -set the ``first`` attribute appropriately in the returned object. - -For example, on a system set to US/Eastern timezone:: - - >>> datetime.fromtimestamp(1414906200) - datetime.datetime(2014, 11, 2, 1, 30) - >>> datetime.fromtimestamp(1414906200 + 3600) - datetime.datetime(2014, 11, 2, 1, 30, first=False) - - Combining and splitting date and time ..................................... @@ -233,11 +258,27 @@ ``first`` attribute to the resulting ``datetime.time`` instance. +Pickles +....... + +Pickle sizes for the ``datetime.datetime`` and ``datetime.time`` +objects will not change. The ``first`` flag will be encoded in the +first bit of the 5th byte of the ``datetime.datetime`` pickle payload +or the 2nd byte of the datetime.time. In the `current implementation`_ +these bytes are used to store minute value (0-59) and the first bit is +always 0. Note that ``first=True`` will be encoded as 0 in the first +bit and ``first=False`` as 1. (This change only affects pickle +format. In the C implementation, the "first" member will get a full byte +to store the actual boolean value.) + + +.. _current implementation: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17 + Implementations of tzinfo in stdlib -................................... +=================================== No new implementations of ``datetime.tzinfo`` abstract class are -introduced in this PEP. The existing (fixed offset) timezones do +proposed in this PEP. The existing (fixed offset) timezones do not introduce ambiguous local times and their ``utcoffset()`` implementation will return the same constant value as they do now regardless of the value of ``first``. @@ -248,27 +289,32 @@ implementation (the ``datetime.timzeone`` class implementing fixed offset timezones) override ``fromutc()``. -New guidelines will be published for implementing concrete timezones -with variable UTC offset. - -Guidelines for new tzinfo implementations ------------------------------------------ +Guidelines for New tzinfo Implementations +========================================= Implementors of concrete ``datetime.tzinfo`` subclasses who want to -support variable UTC offsets (due to DST and other causes) must follow +support variable UTC offsets (due to DST and other causes) should follow these guidelines. -New subclasses must override the base-class ``fromutc()`` method and + +Ignorance is Bliss +------------------ + +New implementations of ``utcoffset()``, ``tzname()`` and ``dst()`` +methods should ignore the value of ``first`` unless they are called on +the ambiguous or missing times. + + +In the DST Fold +--------------- + +New subclasses should override the base-class ``fromutc()`` method and implement it so that in all cases where two UTC times ``u1`` and ``u2`` (``u1`` <``u2``) correspond to the same local time ``fromutc(u1)`` will return an instance with ``first=True`` and ``fromutc(u2)`` will return an instance with ``first=False``. In all -other cases the returned instance must have ``first=True``. - -New implementations of ``utcoffset()`` and ``dst()`` methods should -ignore the value of ``first`` unless they are called on the ambiguous -or missing times. +other cases the returned instance should have ``first=True``. On an ambiguous time introduced at the end of DST, the values returned by ``utcoffset()`` and ``dst()`` methods should be as follows @@ -276,30 +322,37 @@ +-----------------+----------------+------------------+ | | first=True | first=False | +=================+================+==================+ -| utcoff() | stdoff + hour | stdoff | +| utcoffset() | stdoff + dstoff| stdoff | +-----------------+----------------+------------------+ -| dst() | hour | zero | +| dst() | dstoff | zero | +-----------------+----------------+------------------+ -where ``stdoff`` is the standard (non-DST) offset, -``hour = timedelta(hours=1)`` and ``zero = timedelta(0)``. +where ``stdoff`` is the standard (non-DST) offset, ``dstoff`` is the +DST correction (typically ``dstoff = timedelta(hours=1)``) and ``zero += timedelta(0)``. + + +Mind the DST Gap +---------------- On a missing time introduced at the start of DST, the values returned by ``utcoffset()`` and ``dst()`` methods should be as follows - +-----------------+----------------+------------------+ | | first=True | first=False | +=================+================+==================+ -| utcoff() | stdoff | stdoff + hour | +| utcoffset() | stdoff | stdoff + dstoff | +-----------------+----------------+------------------+ -| dst() | zero | hour | +| dst() | zero | dstoff | +-----------------+----------------+------------------+ +Non-DST Folds and Gaps +---------------------- + On ambiguous/missing times introduced by the change in the standard time offset, the ``dst()`` method should return the same value regardless of -the value of ``first`` and the ``utcoff()`` should return values +the value of ``first`` and the ``utcoffset()`` should return values according to the following table: +-----------------+----------------+-----------------------------+ @@ -310,28 +363,11 @@ | missing | oldoff | newoff = oldoff + delta | +-----------------+----------------+-----------------------------+ +where ``delta`` is the size of the fold or the gap. -Pickle size ------------ - -Pickle sizes for the ``datetime.datetime`` and ``datetime.time`` -objects will not change. The ``first`` flag will be encoded in the -first bit of the 5th byte of the ``datetime.datetime`` pickle payload -or the 2nd byte of the datetime.time. In the `current implementation`_ -these bytes are used to store minute value (0-59) and the first bit is -always 0. Note that ``first=True`` will be encoded as 0 in the first -bit and ``first=False`` as 1. (This change only affects pickle -format. In C implementation, the "first" member will get a full byte -to store the actual boolean value.) - -We chose the minute byte to store the the "first" bit because this -choice preserves the natural ordering. - -.. _current implementation: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17 - -Temporal Arithmetics --------------------- +Temporal Arithmetic +=================== The value of "first" will be ignored in all operations except those that involve conversion between timezones. [#]_ As a consequence, @@ -345,15 +381,16 @@ datetime will always have ``first`` set to ``True`` even if the original datetime instance had ``first=False``. -.. [#] As of Python 3.5, ``tzinfo`` is ignored whenever timedelta is - added or subtracted from a ``datetime.datetime`` instance or when - one ``datetime.datetime`` instance is subtracted from another with - the same (even not-None) ``tzinfo``. This may change in the future, - but such changes are outside of the scope of this PEP. +.. [#] Computing a difference between two aware datetime instances + with different values of ``tzinfo`` involves an implicit timezone + conversion. In this case, the result may depend on the value of + the ``first`` flag in either of the instances, but only if the + instance has ``tzinfo`` that accounts for the value of ``first`` + in its ``utcoffset()`` method. Backward and Forward Compatibility ----------------------------------- +================================== This proposal will have little effect on the programs that do not read the ``first`` flag explicitly or use tzinfo implementations that do. @@ -368,16 +405,19 @@ versions. Pickles of instances with ``first=True`` (which is the default) will remain unchanged. + Questions and Answers ===================== -1. Why not call the new flag "isdst"? +Why not call the new flag "isdst"? +---------------------------------- -------- +A non-technical answer +...................... -* Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow! -* Bob: Should I presume initially that summer time (for example, Daylight - Saving Time) is or is not (respectively) in effect for the specified time? +* Alice: Bob - let's have a stargazing party at 01:30 AM tomorrow! +* Bob: Should I presume initially that Daylight Saving Time is or is + not in effect for the specified time? * Alice: Huh? ------- @@ -386,32 +426,77 @@ * Alice: You know, Bob, 01:30 AM will happen twice tomorrow. Which time do you have in mind? * Bob: I did not think about it, but let's pick the first. +------- -2. Why "first"? +A technical reason +.................. -* Rejections: +While the ``tm_isdst`` field of the ``time.struct_time`` object can be +used to disambiguate local times in the fold, the semantics of such +disambiguation are completely different from the proposal in this PEP. - **second** - rejected because "second" is already there. +The main problem with the ``tm_isdst`` field is that it is impossible +to know what value is appropriate for ``tm_isdst`` without knowing the +details about the time zone that are only available to the ``tzinfo`` +implementation. Thus while ``tm_isdst`` is useful in the *output* of +methods such as ``time.localtime``, it is cumbursome as an *input* of +methods such as ``time.mktime``. + +If the programmer misspecifies a non-negative value of ``tm_isdst`` to +``time.mktime``, the result will be time that is 1 hour off and since +there is rarely a way to know anything about DST *before* a call to +``time.mktime`` is made, the only sane choice is usually +``tm_isdst=-1``. + +Unlike ``tm_isdst``, the proposed ``first`` flag has no effect on the +interpretation of the datetime instance unless without that flag two +(or no) interpretations are possible. + +Since it would be very confusing to have something called ``isdst`` +that does not have the same semantics as ``tm_isdst``, we need a +different name. Moreover, the ``datetime.datetime`` class already has +a method called ``dst()`` and if we called ``first`` "isdst", we would +necessarily have situations when "isdst" and ``bool(dst())`` values +are different. + + +Why "first"? +------------ + +This is a working name chosen initially because the obvious +alternative ("second") conflicts with the existing attribute. It has +since became clear that it is desirable to have a flag with the +default value ``False`` and such that chronological ordering of +disambiguated (datetime, flag) pairs would match their lexicographical +order. + +The following alternative names have been proposed: + + **fold** + Suggested by Guido van Rossum and favored by the author. Has + correct connotations and easy mnemonic rules, but at the same + time does not invite unbased assumptions. **later** - rejected because "later" is confusable with "latter". - - **earlier** - rejected because "earlier" has the same issue as "first" (requires - default to be True) but is two characters longer. - -* Remaining possibilities: - + A close contender to "fold". The author dislikes it because + it is confusable with equally fitting "latter," but in the age + of autocompletion everywhere this is a small consideration. A + stronger objection may be that in the case of missing time, we + will have ``later=True`` instance converted to an earlier time by + ``.astimezone(timezone.utc)`` that that with ``later=False``. + Yet again, this can be interpreted as a desirable indication that + the original time is invalid. + **repeated** - this is a strong candidate - - **is_first** - arguably more grammatically correct than "first" + Did not receive any support on the mailing list. **ltdf** - (Local Time Disambiguation Flag) - short and no-one will - attempt to guess what it means without reading the docs. + (Local Time Disambiguation Flag) - short and no-one will attempt + to guess what it means without reading the docs. (Feel free to + use it in discussions with the meaning ltdf=False is the + earlier if you don't want to endorse any of the alternatives + above.) + Implementation ============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 04:39:48 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 22 Aug 2015 02:39:48 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_Tim_Peters_a?= =?utf-8?q?s_an_author=2E?= Message-ID: <20150822023948.22348.92462@psf.io> https://hg.python.org/peps/rev/b3a549df81a4 changeset: 5970:b3a549df81a4 user: Alexander Belopolsky date: Fri Aug 21 22:39:45 2015 -0400 summary: PEP 495: Added Tim Peters as an author. files: pep-0495.txt | 6 +++--- pep-0500.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -2,7 +2,7 @@ Title: Local Time Disambiguation Version: $Revision$ Last-Modified: $Date$ -Author: Alexander Belopolsky +Author: Alexander Belopolsky , Tim Peters Discussions-To: Datetime-SIG Status: Draft Type: Standards Track @@ -473,12 +473,12 @@ The following alternative names have been proposed: **fold** - Suggested by Guido van Rossum and favored by the author. Has + Suggested by Guido van Rossum and favored by one (but disfavored by another) author. Has correct connotations and easy mnemonic rules, but at the same time does not invite unbased assumptions. **later** - A close contender to "fold". The author dislikes it because + A close contender to "fold". One author dislikes it because it is confusable with equally fitting "latter," but in the age of autocompletion everywhere this is a small consideration. A stronger objection may be that in the case of missing time, we diff --git a/pep-0500.txt b/pep-0500.txt --- a/pep-0500.txt +++ b/pep-0500.txt @@ -3,7 +3,7 @@ tzinfo implementations Version: $Revision$ Last-Modified: $Date$ -Author: Alexander Belopolsky +Author: Alexander Belopolsky , Tim Peters Discussions-To: Datetime-SIG Status: Draft Type: Standards Track -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 11:57:54 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 22 Aug 2015 09:57:54 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_Tim=27s_email_address_?= =?utf-8?q?so_PEPs_build_again?= Message-ID: <20150822095753.29065.42612@psf.io> https://hg.python.org/peps/rev/524e0372b08b changeset: 5972:524e0372b08b user: Nick Coghlan date: Sat Aug 22 19:57:41 2015 +1000 summary: Update Tim's email address so PEPs build again files: pep-0020.txt | 2 +- pep-0223.txt | 2 +- pep-0235.txt | 2 +- pep-0236.txt | 2 +- pep-0255.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pep-0020.txt b/pep-0020.txt --- a/pep-0020.txt +++ b/pep-0020.txt @@ -2,7 +2,7 @@ Title: The Zen of Python Version: $Revision$ Last-Modified: $Date$ -Author: tim at zope.com (Tim Peters) +Author: tim.peters at gmail.com (Tim Peters) Status: Active Type: Informational Content-Type: text/plain diff --git a/pep-0223.txt b/pep-0223.txt --- a/pep-0223.txt +++ b/pep-0223.txt @@ -2,7 +2,7 @@ Title: Change the Meaning of \x Escapes Version: $Revision$ Last-Modified: $Date$ -Author: tim at zope.com (Tim Peters) +Author: tim.peters at gmail.com (Tim Peters) Status: Final Type: Standards Track Created: 20-Aug-2000 diff --git a/pep-0235.txt b/pep-0235.txt --- a/pep-0235.txt +++ b/pep-0235.txt @@ -2,7 +2,7 @@ Title: Import on Case-Insensitive Platforms Version: $Revision$ Last-Modified: $Date$ -Author: Tim Peters +Author: Tim Peters Status: Final Type: Standards Track Created: diff --git a/pep-0236.txt b/pep-0236.txt --- a/pep-0236.txt +++ b/pep-0236.txt @@ -2,7 +2,7 @@ Title: Back to the __future__ Version: $Revision$ Last-Modified: $Date$ -Author: Tim Peters +Author: Tim Peters Status: Final Type: Standards Track Created: 26-Feb-2001 diff --git a/pep-0255.txt b/pep-0255.txt --- a/pep-0255.txt +++ b/pep-0255.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: nas at arctrix.com (Neil Schemenauer), - tim at zope.com (Tim Peters), + tim.peters at gmail.com (Tim Peters), magnus at hetland.org (Magnus Lie Hetland) Discussions-To: python-iterators at lists.sourceforge.net Status: Final -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 11:57:53 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 22 Aug 2015 09:57:53 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Major_redesign_of_PEP_501_int?= =?utf-8?q?erpolation?= Message-ID: <20150822095753.19654.82206@psf.io> https://hg.python.org/peps/rev/05f2211ddd10 changeset: 5971:05f2211ddd10 user: Nick Coghlan date: Sat Aug 22 19:57:17 2015 +1000 summary: Major redesign of PEP 501 interpolation files: pep-0501.txt | 429 ++++++++++++++++++++++---------------- 1 files changed, 243 insertions(+), 186 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -1,5 +1,5 @@ PEP: 501 -Title: Translation ready string interpolation +Title: General purpose string interpolation Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan @@ -18,53 +18,83 @@ operation full access to containing namespaces (as with any other expression), rather than being limited to explicitly name references. -This PEP agrees with the basic motivation of PEP 498, but proposes to focus -both the syntax and the implementation on the il8n use case, drawing on the -previous proposals in PEP 292 (which added string.Template) and its predecessor -PEP 215 (which proposed syntactic support, rather than a runtime string -manipulation based approach). The text of this PEP currently assumes that the -reader is familiar with these three previous related proposals. +However, it only offers this capability for string formatting, making it likely +we will see code like the following:: -The interpolation syntax proposed for this PEP is that of PEP 292, but expanded -to allow arbitrary expressions and format specifiers when using the ``${ref}`` -interpolation syntax. The suggested new string prefix is "i" rather than "f", -with the intended mnemonics being either "interpolated string" or -"il8n string":: + os.system(f"echo {user_message}") + +This kind of code is superficially elegant, but poses a significant problem +if the interpolated value ``user_message`` is in fact provided by a user: it's +an opening for a form of code injection attack, where the supplied user data +has not been properly escaped before being passed to the ``os.system`` call. + +To address that problem (and a number of other concerns), this PEP proposes an +alternative approach to compiler supported interpolation, based on a new +``__interpolate__`` magic method, and using a substitution syntax inspired by +that used in ``string.Template`` and ES6 JavaScript, rather than adding a 4th +substitution variable syntax to Python. + +Proposal +======== + +This PEP proposes that the new syntax:: + + value = !interpolator "Substitute $names and ${expressions} at runtime" + +be interpreted as:: + + _raw_template = "Substitute $names and ${expressions} at runtime" + _parsed_fields = ( + ("Substitute ", 0, "names", "", ""), + (" and ", 1, "expressions", "", ""), + (" at runtime", None, None, None, None), + ) + _field_values = (names, expressions) + value = interpolator.__interpolate__(_raw_template, + _parsed_fields, + _field_values) + +Whitespace would be permitted between the interpolator name and the opening +quote, but not required in most cases. + +The ``str`` builtin type would gain an ``__interpolate__`` implementation that +supported the following ``str.format`` based semantics:: >>> import datetime >>> name = 'Jane' >>> age = 50 >>> anniversary = datetime.date(1991, 10, 12) - >>> i'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' + >>> !str'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' 'My name is Jane, my age next year is 51, my anniversary is Saturday, October 12, 1991.' - >>> i'She said her name is ${name!r}.' + >>> !str'She said her name is ${name!r}.' "She said her name is 'Jane'." -This PEP also proposes the introduction of three new builtin functions, -``__interpolate__``, ``__interpolateb__`` and ``__interpolateu__``, which -implement key aspects of the interpolation process, and may be overridden in -accordance with the usual mechanisms for shadowing builtin functions. +The interpolation prefix could be used with single-quoted, double-quoted and +triple quoted strings. It may also be used with raw strings, but in that case +whitespace would be required between the interpolator name and the trailing +string. This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms, as those will remain valuable when formatting strings that are not present directly in the source code of the application. -The key aim of this PEP that isn't inherited from PEP 498 is to help ensure -that future Python applications are written in a "translation ready" way, where -many interface strings that may need to be translated to allow an application -to be used in multiple languages are flagged as a natural consequence of the -development process, even though they won't be translated by default. - Rationale ========= PEP 498 makes interpolating values into strings with full access to Python's lexical namespace semantics simpler, but it does so at the cost of introducing -yet another string interpolation syntax. +yet another string interpolation syntax, and also creates a situation where +interpolating values into sensitive targets like SQL queries, shell commands +and HTML templates will enjoy a much cleaner syntax when handled without +regard for code injection attacks than when they are handled correctly. + +This PEP proposes to handle the latter issue by always specifying an explicit +interpolator for interpolation operations, and the former by adopting the +``string.Template`` substitution syntax defined in PEP 292. The interpolation syntax devised for PEP 292 is deliberately simple so that the -template strings can be extracted into an il8n message catalog, and passed to +template strings can be extracted into an i18n message catalog, and passed to translators who may not themselves be developers. For these use cases, it is important that the interpolation syntax be as simple as possible, as the translators are responsible for preserving the substition markers, even as @@ -77,31 +107,35 @@ that flexibility to the ``${ref}`` construct in PEP 292, and allows translation tools the option of rejecting usage of that more advanced syntax at runtime, rather than categorically rejecting it at compile time. The proposed permitted -expressions inside ``${ref}`` are exactly as defined in PEP 498. +expressions, conversion specifiers, and format specifiers inside ``${ref}`` are +exactly as defined in PEP 498. + +The specific proposal in this PEP is also deliberately close in both syntax +and semantics to the general purpose interpolation syntax introduced to +JavaScript in ES6, as we can reasonably expect a great many Python to be +regularly switching back and forth between user interface code written in +JavaScript and core application code written in Python. Specification ============= -In source code, i-strings are string literals that are prefixed by the -letter 'i'. The string will be parsed into its components at compile time, -which will then be passed to the new ``__interpolate__`` builtin at runtime. +In source code, interpolation expressions are introduced by the new character +``!``. This is a new kind of expression, consisting of:: -The 'i' prefix may be combined with 'b', where the 'i' must appear first, in -which case ``__interpolateb__`` will be called rather than ``__interpolate__``. -Similarly, 'i' may also be combined with 'u' to call ``__interpolateu__`` -rather than ``__interpolate__``. + !DOTTED_NAME TEMPLATE_STRING -The 'i' prefix may also be combined with 'r', with or without 'b' or 'u', to -produce raw i-strings. This disables backslash escape sequences in the string -literal as usual, but has no effect on the runtime interpolation behaviour. +Similar to ``yield`` expressions, this construct can be used without +parentheses as a standalone expression statement, as the sole expression on the +right hand side of an assignment or return statement, and as the sole argument +to a function. In other situations, it requires containing parentheses to avoid +ambiguity. -In all cases, the only permitted location for the 'i' prefix is before all other -prefix characters - it indicates a runtime operation, which is largely -independent of the compile time prefixes (aside from calling different -interpolation functions when combined with 'b' or 'u'). +The template string must be a Unicode string (byte strings are not permitted), +and string literal concatenation operates as normal within the template string +component of the expression. -i-strings are parsed into literals and expressions. Expressions +The template string is parsed into literals and expressions. Expressions appear as either identifiers prefixed with a single "$" character, or surrounded be a leading '${' and a trailing '}. The parts of the format string that are not expressions are separated out as string literals. @@ -110,63 +144,68 @@ and is considered part of the literal text, rather than as introducing an expression. -These components are then organised into 3 parallel tuples: +These components are then organised into a tuple of tuples, and passed to the +``__interpolate__`` method of the interpolator identified by the given +name:: -* parsed format string fields -* expression text -* expression values + DOTTED_NAME.__interpolate__(TEMPLATE_STRING, + , + ) -And then passed to the ``__interpolate__`` builtin at runtime:: +The template string field tuple is inspired by the interface of +``string.Formatter.parse``, and consists of a series of 5-tuples each +containing: - __interpolate__(fields, expressions, values) +* a leading string literal (may be the empty string) +* the substitution field position (zero-based enumeration) +* the substitution expression text +* the substitution conversion specifier (as defined by str.format) +* the substitution format specifier (as defined by str.format) -The format string field tuple is inspired by the interface of -``string.Formatter.parse``, and consists of a series of 4-tuples each containing -a leading literal, together with a trailing field number, format specifier, -and conversion specifier. If a given substition field has no leading literal -section, format specifier or conversion specifier, then the corresponding -elements in the tuple are the empty string. If the final part of the string -has no trailing substitution field, then the field number, format specifier +If a given substition field has no leading literal section, format specifier +or conversion specifier, then the corresponding elements in the tuple are the +empty string. If the final part of the string has no trailing substitution +field, then the field number, format specifier and conversion specifier will all be ``None``. The expression text is simply the text of each interpolated expression, as it appeared in the original string, but without the leading and/or surrounding expression markers. -The expression values are the result of evaluating the interpolated expressions -in the exact runtime context where the i-string appears in the source code. +The substitution field values tuple is created by evaluating the interpolated +expressions in the exact runtime context where the interpolation expression +appears in the source code. -For the following example i-string:: +For the following example interpolation expression:: - i'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl'``, + !str 'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl' -the fields tuple would be:: +the parsed fields tuple would be:: ( - ('abc', 0, 'spec1', ''), - ('', 1, 'spec2' 'r'), - (def', 2, '', 's'), - ('ghi', 3, '', ''), - ('$jkl', None, None, None) + ('abc', 0, 'expr1', '', 'spec1'), + ('', 1, 'expr2', 'r', 'spec2'), + (def', 2, 'expr3', 's', ''), + ('ghi', 3, 'ident', '', ''), + ('$jkl', None, None, None, None) ) -For the same example, the expression text and value tuples would be:: +While the field values tupe would be:: - ('expr1', 'expr2', 'expr3', 'ident') # Expression text - (expr1, expr2, expr2, ident) # Expression values + (expr1, expr2, expr3, ident) -The fields and expression text tuples can be constant folded at compile time, -while the expression values tuple will always need to be constructed at runtime. +The parsed fields tuple can be constant folded at compile time, while the +expression values tuple will always need to be constructed at runtime. -The default ``__interpolate__`` implementation would have the following +The ``str.__interpolate__`` implementation would have the following semantics, with field processing being defined in terms of the ``format`` builtin and ``str.format`` conversion specifiers:: _converter = string.Formatter().convert_field - def __interpolate__(fields, expressions, values): + def __interpolate__(raw_template, fields, values): template_parts = [] - for leading_text, field_num, format_spec, conversion in fields: + for leading_text, field_num, expr, conversion, format_spec in fields: template_parts.append(leading_text) if field_num is not None: value = values[field_num] @@ -176,167 +215,162 @@ template_parts.append(field_str) return "".join(template_parts) -The default ``__interpolateu__`` implementation would be the -``__interpolate__`` builtin. +Writing custom interpolators +---------------------------- -The default ``__interpolateb__`` implementation would be defined in terms of -the binary mod-formatting reintroduced in PEP 461:: +To simplify the process of writing custom interpolators, it is proposed to add +a new builtin decorator, ``interpolator``, which would be defined as:: - def __interpolateb__(fields, expressions, values): - template_parts = [] - for leading_data, field_num, format_spec, conversion in fields: - template_parts.append(leading_data) - if field_num is not None: - if conversion: - raise ValueError("Conversion specifiers not supported " - "in default binary interpolation") - value = values[field_num] - field_data = ("%" + format_spec) % (value,) - template_parts.append(field_data) - return b"".join(template_parts) + def interpolator(f): + f.__interpolate__ = f.__call__ + return f -This definition permits examples like the following:: +This allows new interpolators to be written as:: - >>> data = 10 - >>> ib'$data' - b'10' - >>> b'${data:%4x}' - b' a' - >>> b'${data:#4x}' - b' 0xa' - >>> b'${data:04X}' - b'000A' + @interpolator + def my_custom_interpolator(raw_template, parsed_fields, field_values): + ... Expression evaluation --------------------- -The expressions that are extracted from the string are evaluated in -the context where the i-string appeared. This means the expression has -full access to local, nonlocal and global variables. Any valid Python -expression can be used inside ``${}``, including function and method calls. -References without the surrounding braces are limited to looking up single -identifiers. +The subexpressions that are extracted from the interpolation expression are +evaluated in the context where the interpolation expression appears. This means +the expression has full access to local, nonlocal and global variables. Any +valid Python expression can be used inside ``${}``, including function and +method calls. References without the surrounding braces are limited to looking +up single identifiers. -Because the i-strings are evaluated where the string appears in the -source code, there is no additional expressiveness available with -i-strings. There are also no additional security concerns: you could -have also just written the same expression, not inside of an -i-string:: +Because the substitution expressions are evaluated where the string appears in +the source code, there are no additional security concerns related to the +contents of the expression itself, as you could have also just written the +same expression and used runtime field parsing:: >>> bar=10 >>> def foo(data): ... return data + 20 ... - >>> i'input=$bar, output=${foo(bar)}' + >>> !str 'input=$bar, output=${foo(bar)}' 'input=10, output=30' -Is equivalent to:: +Is essentially equivalent to:: >>> 'input={}, output={}'.format(bar, foo(bar)) 'input=10, output=30' -Format specifiers ------------------ +Handling code injection attacks +------------------------------- -Format specifiers are not interpreted by the i-string parser - that is -handling at runtime by the called interpolation function. +The proposed interpolation expressions make it potentially attractive to write +code like the following:: -Concatenating strings ---------------------- + myquery = !str "SELECT $column FROM $table;" + mycommand = !str "cat $filename" + mypage = !str "$content" -As i-strings are shorthand for a runtime builtin function call, implicit -concatenation is a syntax error (similar to attempting implicit concatenation -between bytes and str literals):: +These all represent potential vectors for code injection attacks, if any of the +variables being interpolated happen to come from an untrusted source. The +specific proposal in this PEP is designed to make it straightforward to write +use case specific interpolators that take care of quoting interpolated values +appropriately for the relevant security context:: - >>> i"interpolated" "not interpolated" - File "", line 1 - SyntaxError: cannot mix interpolation call with plain literal + myquery = !sql "SELECT $column FROM $table;" + mycommand = !sh "cat $filename" + mypage = !html "$content" + +This PEP does not cover adding such interpolators to the standard library, +but instead ensures they can be readily provided by third party libraries. + +(Although it's tempting to propose adding __interpolate__ implementations to +``subprocess.call``, ``subprocess.check_call`` and ``subprocess.check_output``) + +Format and conversion specifiers +-------------------------------- + +Aside from separating them out from the substitution expression, format and +conversion specifiers are otherwise treated as opaque strings by the +interpolation template parser - assigning semantics to those (or, alternatively, +prohibiting their use) is handled at runtime by the specified interpolator. Error handling -------------- -Either compile time or run time errors can occur when processing -i-strings. Compile time errors are limited to those errors that can be -detected when parsing an i-string into its component tuples. These errors all -raise SyntaxError. +Either compile time or run time errors can occur when processing interpolation +expressions. Compile time errors are limited to those errors that can be +detected when parsing a template string into its component tuples. These +errors all raise SyntaxError. Unmatched braces:: - >>> i'x=${x' + >>> !str 'x=${x' File "", line 1 SyntaxError: missing '}' in interpolation expression Invalid expressions:: - >>> i'x=${!x}' + >>> !str 'x=${!x}' File "", line 1 !x ^ SyntaxError: invalid syntax Run time errors occur when evaluating the expressions inside an -i-string. See PEP 498 for some examples. +template string. See PEP 498 for some examples. -Different interpolation functions may also impose additional runtime +Different interpolators may also impose additional runtime constraints on acceptable interpolated expressions and other formatting details, which will be reported as runtime exceptions. -Leading whitespace in expressions is not skipped ------------------------------------------------- - -Unlike PEP 498, leading whitespace in expressions doesn't need to be skipped - -'$' is not a legal character in Python's syntax, so it can't appear inside -a ``${}`` field except as part of another string, whether interpolated or not. - Internationalising interpolated strings ======================================= -So far, this PEP has said nothing practical about internationalisation - only -formatting text using either str.format or bytes.__mod__ semantics depending -on whether or not a str or bytes object is being interpolated. +Since this PEP derives its interpolation syntax from the internationalisation +focused PEP 292, it's worth considering the potential implications this PEP +may have for the internationalisation use case. -Internationalisation enters the picture by overriding the ``__interpolate__`` -builtin on a module-by-module basis. For example, the following implementation -would delegate interpolation calls to string.Template:: +Internationalisation enters the picture by writing a custom interpolator that +performs internationalisation. For example, the following implementation +would delegate interpolation calls to ``string.Template``:: - def _interpolation_fields_to_template(fields, expressions): - if not all(expr.isidentifier() for expr in expressions): - raise ValueError("Only variable substitions permitted for il8n") - template_parts = [] - for literal_text, field_num, format_spec, conversion in fields: - if format_spec: - raise ValueError("Format specifiers not permitted for il8n") - if conversion: - raise ValueError("Conversion specifiers not permitted for il8n") - template_parts.append(literal_text) - if field_num is not None: - template_parts.append("${" + expressions[field_num] + "}") - return "".join(template_parts) - - def __interpolate__(fields, expressions, values): - catalog_str = _interpolation_fields_to_template(fields, expressions) - translated = _(catalog_str) - values = {k:v for k, v in zip(expressions, values)} + @interpolator + def i18n(template, fields, values): + translated = gettext.gettext(template) + values = _build_interpolation_map(fields, values) return string.Template(translated).safe_substitute(values) -If a module were to import that definition of __interpolate__ into the -module namespace, then: + def _build_interpolation_map(fields, values): + field_values = {} + for literal_text, field_num, expr, conversion, format_spec in fields: + assert expr.isidentifier() and not conversion and not format_spec + if field_num is not None: + field_values[expr] = values[field_num] + return field_values -* Any i"translated & interpolated" strings would be translated -* Any iu"untranslated & interpolated" strings would not be translated -* Any ib"untranslated & interpolated" strings would not be translated -* Any other string and bytes literals would not be translated unless explicitly - passed to the relevant translation machinery at runtime +And would then be invoked as:: -This shifts the behaviour from the status quo, where translation support needs -to be added explicitly to each string requiring translation to one where -opting *in* to translation is done on a module by module basis, and -individual interpolated strings can then be opted *out* of translation by -adding the "u" prefix to the string literal in order to call -``__interpolateu__`` instead of ``__interpolate__``. + print(!i18n "This is a $translated $message") +Any actual implementation would need to address other issues (most notably +message catalog extraction), but this gives the general idea of what might be +possible. + +It's also worth noting that one of the benefits of the ``$`` based substitution +syntax in this PEP is its compatibility with Mozilla's +`l20n syntax `__, which uses ``{{ name }}`` for global +substitution, and ``{{ $user }}`` for local context substitution. + +With the syntax in this PEP, an l20n interpolator could be written as:: + + translated = !l20n "{{ $user }} is running {{ appname }}" + +With the syntax proposed in PEP 498 (and neglecting the difficulty of doing +catalog lookups using PEP 498's semantics), the necessary brace escaping would +make the string look like this in order to interpolating the user variable +while preserving all of the expected braces:: + + interpolated = "{{{{ ${user} }}}} is running {{{{ appname }}}}" Discussion ========== @@ -344,19 +378,42 @@ Refer to PEP 498 for additional discussion, as several of the points there also apply to this PEP. -Preserving the unmodified format string ---------------------------------------- +Compatibility with IPython magic strings +---------------------------------------- -A lot of the complexity in the il8n example is actually in recreating the -original format string from its component parts. It may make sense to preserve -and pass that entire string to the interpolation function, in addition to -the broken down field definitions. +IPython uses "!" to introduce custom interactive constructs. These are only +used at statement level, and could continue to be special cased in the +IPython runtime. -This approach would also allow translators to more consistently benefit from -the simplicity of the PEP 292 approach to string formatting (in the example -above, surrounding braces are added to the catalog strings even for cases that -don't need them) +This existing usage *did* help inspire the syntax proposed in this PEP. +Preserving the raw template string +---------------------------------- + +Earlier versions of this PEP failed to make the raw template string available +to interpolators. This greatly complicated the i18n example, as it needed to +reconstruct the original template to pass to the message catalog lookup. + +Using a magic method rather than a global name lookup +----------------------------------------------------- + +Earlier versions of this PEP used an ``__interpolate__`` builtin, rather than +a magic method on an explicitly named interpolator. Naming the interpolator +eliminated a lot of the complexity otherwise associated with shadowing the +builtin function in order to modify the semantics of interpolation. + +Relative order of conversion and format specifier in parsed fields +------------------------------------------------------------------ + +The relative order of the conversion specifier and the format specifier in the +substitution field 5-tuple is defined to match the order they appear in the +format string, which is unfortunately the inverse of the way they appear in the +``string.Formatter.parse`` 4-tuple. + +I consider this a design defect in ``string.Formatter.parse``, so I think it's +worth fixing it in for the customer interpolator API, since the tuple already +has other differences (like including both the field position number *and* the +text of the expression). References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 13:17:39 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 22 Aug 2015 11:17:39 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_add_logging_exampl?= =?utf-8?q?es=2C_other_tweaks?= Message-ID: <20150822111738.21443.47679@psf.io> https://hg.python.org/peps/rev/3e6af2d1d0bd changeset: 5973:3e6af2d1d0bd user: Nick Coghlan date: Sat Aug 22 21:17:31 2015 +1000 summary: PEP 501: add logging examples, other tweaks files: pep-0501.txt | 57 ++++++++++++++++++++++++++++++++------- 1 files changed, 47 insertions(+), 10 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -83,11 +83,13 @@ ========= PEP 498 makes interpolating values into strings with full access to Python's -lexical namespace semantics simpler, but it does so at the cost of introducing -yet another string interpolation syntax, and also creates a situation where -interpolating values into sensitive targets like SQL queries, shell commands -and HTML templates will enjoy a much cleaner syntax when handled without -regard for code injection attacks than when they are handled correctly. +lexical namespace semantics simpler, but it does so at the cost of creating a +situation where interpolating values into sensitive targets like SQL queries, +shell commands and HTML templates will enjoy a much cleaner syntax when handled +without regard for code injection attacks than when they are handled correctly. +It also has the effect of introducing yet another syntax for substitution +expressions into Python, when we already have 3 (``str.format``, +``bytes.__mod__`` and ``string.Template``) This PEP proposes to handle the latter issue by always specifying an explicit interpolator for interpolation operations, and the former by adopting the @@ -112,8 +114,8 @@ The specific proposal in this PEP is also deliberately close in both syntax and semantics to the general purpose interpolation syntax introduced to -JavaScript in ES6, as we can reasonably expect a great many Python to be -regularly switching back and forth between user interface code written in +JavaScript in ES6, as we can reasonably expect a great many Python developers +to be regularly switching back and forth between user interface code written in JavaScript and core application code written in Python. @@ -190,7 +192,7 @@ ('$jkl', None, None, None, None) ) -While the field values tupe would be:: +While the field values tuple would be:: (expr1, expr2, expr3, ident) @@ -337,8 +339,8 @@ @interpolator def i18n(template, fields, values): translated = gettext.gettext(template) - values = _build_interpolation_map(fields, values) - return string.Template(translated).safe_substitute(values) + value_map = _build_interpolation_map(fields, values) + return string.Template(translated).safe_substitute(value_map) def _build_interpolation_map(fields, values): field_values = {} @@ -372,6 +374,24 @@ interpolated = "{{{{ ${user} }}}} is running {{{{ appname }}}}" + +Possible integration with the logging module +============================================ + +One of the challenges with the logging module has been that previously been +unable to devise a reasonable migration strategy away from the use of +printf-style formatting. The runtime parsing and interpolation overhead for +logging messages also poses a problem for extensive logging of runtime events +for monitoring purposes. + +While beyond the scope of this initial PEP, the proposal described here could +potentially be applied to the logging module's event reporting APIs, permitting +relevant details to be captured using forms like:: + + !logging.debug "Event: $event; Details: $data" + !logging.critical "Error: $error; Details: $data" + + Discussion ========== @@ -415,6 +435,23 @@ has other differences (like including both the field position number *and* the text of the expression). +Using call syntax to support keyword-only parameters +---------------------------------------------------- + +The logging examples could potentially be better written as:: + + !logging.debug("Event: $event; Details: $data") + !logging.critical("Error: $error; Details: $data") + +The key benefit this would provide is access to keyword arguments, so you +could write: + + !logging.critical("Error: $error; Details: $data", exc_info=True) + +In this version, an interpolation expression would largely be syntactically +equivalent to a normal function call, except that it would be restricted to +accepting a single string literal as its sole position argument. + References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 23:04:41 2015 From: python-checkins at python.org (nick.coghlan) Date: Sat, 22 Aug 2015 21:04:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_switch_to_a_more_n?= =?utf-8?q?ormal_binary_operator?= Message-ID: <20150822210441.19640.50332@psf.io> https://hg.python.org/peps/rev/a7d8ee21a9dd changeset: 5974:a7d8ee21a9dd user: Nick Coghlan date: Sun Aug 23 07:04:33 2015 +1000 summary: PEP 501: switch to a more normal binary operator files: pep-0501.txt | 112 +++++++++++++++++++++++--------------- 1 files changed, 67 insertions(+), 45 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -29,19 +29,30 @@ has not been properly escaped before being passed to the ``os.system`` call. To address that problem (and a number of other concerns), this PEP proposes an -alternative approach to compiler supported interpolation, based on a new -``__interpolate__`` magic method, and using a substitution syntax inspired by +alternative approach to compiler supported interpolation, based on a new ``$`` +binary operator with a syntactically constrained right hand side, a new +``__interpolate__`` magic method, and a substitution syntax inspired by that used in ``string.Template`` and ES6 JavaScript, rather than adding a 4th substitution variable syntax to Python. +Some examples of the proposed syntax:: + + msg = str$'My age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' + print(_$"This is a $translated $message") + translated = l20n$"{{ $user }} is running {{ appname }}" + myquery = sql$"SELECT $column FROM $table;" + mycommand = sh$"cat $filename" + mypage = html$"${response.body}" + Proposal ======== -This PEP proposes that the new syntax:: +This PEP proposes the introduction of a new binary operator specifically for +interpolation of arbitrary expressions:: - value = !interpolator "Substitute $names and ${expressions} at runtime" + value = interpolator $ "Substitute $names and ${expressions} at runtime" -be interpreted as:: +This would be effectively interpreted as:: _raw_template = "Substitute $names and ${expressions} at runtime" _parsed_fields = ( @@ -54,25 +65,24 @@ _parsed_fields, _field_values) -Whitespace would be permitted between the interpolator name and the opening -quote, but not required in most cases. +The right hand side of the new operator would be syntactically constrained to +be a string literal. The ``str`` builtin type would gain an ``__interpolate__`` implementation that -supported the following ``str.format`` based semantics:: +supported the following ``str.format`` inspired semantics:: >>> import datetime >>> name = 'Jane' >>> age = 50 >>> anniversary = datetime.date(1991, 10, 12) - >>> !str'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' + >>> str$'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' 'My name is Jane, my age next year is 51, my anniversary is Saturday, October 12, 1991.' - >>> !str'She said her name is ${name!r}.' + >>> str$'She said her name is ${name!r}.' "She said her name is 'Jane'." -The interpolation prefix could be used with single-quoted, double-quoted and -triple quoted strings. It may also be used with raw strings, but in that case -whitespace would be required between the interpolator name and the trailing -string. +The interpolation operator could be used with single-quoted, double-quoted and +triple quoted strings, including raw strings. It would not support bytes +literals as the right hand side of the expression. This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms, as those will remain valuable when formatting @@ -122,18 +132,16 @@ Specification ============= -In source code, interpolation expressions are introduced by the new character -``!``. This is a new kind of expression, consisting of:: +This PEP proposes the introduction of ``$`` as a new binary operator designed +specifically to support interpolation of template strings:: - !DOTTED_NAME TEMPLATE_STRING + INTERPOLATOR $ TEMPLATE_STRING -Similar to ``yield`` expressions, this construct can be used without -parentheses as a standalone expression statement, as the sole expression on the -right hand side of an assignment or return statement, and as the sole argument -to a function. In other situations, it requires containing parentheses to avoid -ambiguity. +This would work as a normal binary operator (precedence TBD), with the +exception that the template string would be syntactically constrained to be a +string literal, rather than permitting arbitrary expressions. -The template string must be a Unicode string (byte strings are not permitted), +The template string must be a Unicode string (bytes literals are not permitted), and string literal concatenation operates as normal within the template string component of the expression. @@ -180,7 +188,7 @@ For the following example interpolation expression:: - !str 'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl' + str$'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl' the parsed fields tuple would be:: @@ -253,7 +261,7 @@ >>> def foo(data): ... return data + 20 ... - >>> !str 'input=$bar, output=${foo(bar)}' + >>> str$'input=$bar, output=${foo(bar)}' 'input=10, output=30' Is essentially equivalent to:: @@ -267,9 +275,9 @@ The proposed interpolation expressions make it potentially attractive to write code like the following:: - myquery = !str "SELECT $column FROM $table;" - mycommand = !str "cat $filename" - mypage = !str "$content" + myquery = str$"SELECT $column FROM $table;" + mycommand = str$"cat $filename" + mypage = str$"${response.body}" These all represent potential vectors for code injection attacks, if any of the variables being interpolated happen to come from an untrusted source. The @@ -277,9 +285,9 @@ use case specific interpolators that take care of quoting interpolated values appropriately for the relevant security context:: - myquery = !sql "SELECT $column FROM $table;" - mycommand = !sh "cat $filename" - mypage = !html "$content" + myquery = sql$"SELECT $column FROM $table;" + mycommand = sh$"cat $filename" + mypage = html$"${response.body}" This PEP does not cover adding such interpolators to the standard library, but instead ensures they can be readily provided by third party libraries. @@ -305,13 +313,13 @@ Unmatched braces:: - >>> !str 'x=${x' + >>> str$'x=${x' File "", line 1 SyntaxError: missing '}' in interpolation expression Invalid expressions:: - >>> !str 'x=${!x}' + >>> str$'x=${!x}' File "", line 1 !x ^ @@ -350,9 +358,9 @@ field_values[expr] = values[field_num] return field_values -And would then be invoked as:: +And would could then be invoked as:: - print(!i18n "This is a $translated $message") + print(_$"This is a $translated $message") Any actual implementation would need to address other issues (most notably message catalog extraction), but this gives the general idea of what might be @@ -365,11 +373,11 @@ With the syntax in this PEP, an l20n interpolator could be written as:: - translated = !l20n "{{ $user }} is running {{ appname }}" + translated = l20n$"{{ $user }} is running {{ appname }}" With the syntax proposed in PEP 498 (and neglecting the difficulty of doing catalog lookups using PEP 498's semantics), the necessary brace escaping would -make the string look like this in order to interpolating the user variable +make the string look like this in order to interpolate the user variable while preserving all of the expected braces:: interpolated = "{{{{ ${user} }}}} is running {{{{ appname }}}}" @@ -388,8 +396,8 @@ potentially be applied to the logging module's event reporting APIs, permitting relevant details to be captured using forms like:: - !logging.debug "Event: $event; Details: $data" - !logging.critical "Error: $error; Details: $data" + logging.debug$"Event: $event; Details: $data" + logging.critical$"Error: $error; Details: $data" Discussion @@ -398,14 +406,28 @@ Refer to PEP 498 for additional discussion, as several of the points there also apply to this PEP. -Compatibility with IPython magic strings ----------------------------------------- +Determining relative precedence +------------------------------- -IPython uses "!" to introduce custom interactive constructs. These are only -used at statement level, and could continue to be special cased in the -IPython runtime. +The PEP doesn't currently specify the relative precedence of the new operator, +as the only examples considered so far concern standalone expressions or simple +variable assignments. -This existing usage *did* help inspire the syntax proposed in this PEP. +Development of a reference implementation based on the PEP 498 reference +implementation may help answer that question. + +Deferring support for binary interpolation +------------------------------------------ + +Supporting binary interpolation with this syntax would be relatively +straightforward (just a matter of relaxing the syntactic restrictions on the +right hand side of the operator), but poses a signficant likelihood of +producing confusing type errors when a text interpolator was presented with +binary input. + +Since the proposed operator is useful without binary interpolation support, and +such support can be readily added later, further consideration of binary +interpolation is considered out of scope for the current PEP. Preserving the raw template string ---------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 23:24:20 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 22 Aug 2015 21:24:20 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Are_two_values_eno?= =?utf-8?q?ugh=3F?= Message-ID: <20150822212420.21447.37019@psf.io> https://hg.python.org/peps/rev/1d8bc4791634 changeset: 5975:1d8bc4791634 user: Alexander Belopolsky date: Sat Aug 22 17:24:15 2015 -0400 summary: PEP 495: Are two values enough? files: pep-0495.txt | 112 +++++++++++++++++++++++++++++++++++++- 1 files changed, 107 insertions(+), 5 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -396,8 +396,8 @@ the ``first`` flag explicitly or use tzinfo implementations that do. The only visible change for such programs will be that conversions to and from POSIX timestamps will now round-trip correctly (up to -floating point rounding). Programs that implemented work-arounds to -the old incorrect behavior will need to be modified. +floating point rounding). Programs that implemented a work-around to +the old incorrect behavior may need to be modified. Pickles produced by older programs will remain fully forward compatible. Only datetime/time instances with ``first=False`` pickled @@ -439,10 +439,10 @@ to know what value is appropriate for ``tm_isdst`` without knowing the details about the time zone that are only available to the ``tzinfo`` implementation. Thus while ``tm_isdst`` is useful in the *output* of -methods such as ``time.localtime``, it is cumbursome as an *input* of +methods such as ``time.localtime``, it is cumbersome as an *input* of methods such as ``time.mktime``. -If the programmer misspecifies a non-negative value of ``tm_isdst`` to +If the programmer misspecified a non-negative value of ``tm_isdst`` to ``time.mktime``, the result will be time that is 1 hour off and since there is rarely a way to know anything about DST *before* a call to ``time.mktime`` is made, the only sane choice is usually @@ -480,7 +480,7 @@ **later** A close contender to "fold". One author dislikes it because it is confusable with equally fitting "latter," but in the age - of autocompletion everywhere this is a small consideration. A + of auto-completion everywhere this is a small consideration. A stronger objection may be that in the case of missing time, we will have ``later=True`` instance converted to an earlier time by ``.astimezone(timezone.utc)`` that that with ``later=False``. @@ -498,6 +498,108 @@ above.) +Are two values enough? +--------------------------------------- + +The ``time.mktime`` interface allows three values for the ``tm_isdst`` +flag: -1, 0, and 1. As we explained above, -1 (asking ``mktime`` to +determine whether DST is in effect for the given time from the rest of +the fields) is the only choice that is useful in practice. + +With the ``first`` flag, however, ``datetime.timestamp()`` will return +the same value as ``mktime`` with ``tm_isdst=-1`` in 99.98% of the +time for most time zones with DST transitions. Moreover, +``tm_isdst=-1``-like behavior is specified *regardless* of the value +of ``first``. + +It is only in the 0.02% cases (2 hours per year) that the +``datetime.timestamp()`` and ``mktime`` with ``tm_isdst=-1`` may +disagree. However, even in this case, most of the ``mktime`` +implementations will return the ``first=True`` or the ``first=False`` +value even though relevant standards allow ``mktime`` to return -1 and +set an error code in those cases. + +In other words, ``tm_isdst=-1`` behavior is not missing from this PEP. +To the contrary, it is the only behavior provided in two different +well-defined flavors. The behavior that is missing is when a given +local hour is interpreted as a different local hour because of the +misspecified ``tm_isdst``. + +For example, in the DST-observing time zones in the Northern +hemisphere (where DST is in effect in June) one can get + +.. code:: + + >>> from time import mktime, localtime + >>> t = mktime((2015, 6, 1, 12, 0, 0, -1, -1, 0)) + >>> localtime(t)[:] + (2015, 6, 1, 13, 0, 0, 0, 152, 1) + +Note that 12:00 was interpreted as 13:00 by ``mktime``. With the +``datetime.timestamp``, ``datetime.fromtimestamp``, it is currently +guaranteed that + +.. code:: + + >>> t = datetime.datetime(2015, 6, 1, 12).timestamp() + >>> datetime.datetime.fromtimestamp(t) + datetime.datetime(2015, 6, 1, 12, 0) + +This PEP extends the same guarantee to both values of ``first``: + +.. code:: + + >>> t = datetime.datetime(2015, 6, 1, 12, first=True).timestamp() + >>> datetime.datetime.fromtimestamp(t) + datetime.datetime(2015, 6, 1, 12, 0) + +.. code:: + + >>> t = datetime.datetime(2015, 6, 1, 12, first=False).timestamp() + >>> datetime.datetime.fromtimestamp(t) + datetime.datetime(2015, 6, 1, 12, 0) + +Thus one of the suggested uses for ``first=-1`` -- to match the legacy +behavior -- is not needed. Either choice of ``first`` will match the +old behavior except in the few cases where the old behavior was +undefined. + +Another suggestion was to use ``first=-1`` or ``first=None`` to +indicate that the program truly has no means to deal with the folds +and gaps and ``dt.utcoffset()`` should raise an error whenever ``dt`` +represents an ambiguous or missing local time. + +The main problem with this proposal, is that ``dt.utcoffset()`` is +used internally in situations where raising an error is not an option: +for example, in dictionary lookups or list/set membership checks. So +strict gap/fold checking behavior would need to be controlled by a +separate flag, say ``dt.utcoffset(raise_on_gap=True, +raise_on_fold=False)``. However, this functionality can be easily +implemented in user code: + +.. code:: + + def utcoffset(dt, raise_on_gap=True, raise_on_fold=False): + u = dt.utcoffset() + v = dt.replace(first=not dt.first).utcoffset() + if u == v: + return u + if (u < v) == dt.first: + if raise_on_fold: + raise AmbiguousTimeError + else: + if raise_on_gap: + raise MissingTimeError + return u + +Moreover, raising an error in the problem cases is only one of many +possible solutions. An interactive program can ask the user for +additional input, while a server process may log a warning and take an +appropriate default action. We cannot possibly provide functions for +all possible user requirements, but this PEP provides the means to +implement any desired behavior in a few lines of code. + + Implementation ============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 22 23:33:31 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 22 Aug 2015 21:33:31 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_typo?= Message-ID: <20150822213330.21449.5065@psf.io> https://hg.python.org/peps/rev/3e239163d866 changeset: 5976:3e239163d866 user: Alexander Belopolsky date: Sat Aug 22 17:33:28 2015 -0400 summary: PEP 495: typo files: pep-0495.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -465,7 +465,7 @@ This is a working name chosen initially because the obvious alternative ("second") conflicts with the existing attribute. It has -since became clear that it is desirable to have a flag with the +since become clear that it is desirable to have a flag with the default value ``False`` and such that chronological ordering of disambiguated (datetime, flag) pairs would match their lexicographical order. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 03:22:33 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 23 Aug 2015 01:22:33 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Are_two_values_eno?= =?utf-8?q?ugh=3F_//_Backward_Compatibility?= Message-ID: <20150823012233.29059.20629@psf.io> https://hg.python.org/peps/rev/0c65f5c950de changeset: 5977:0c65f5c950de user: Alexander Belopolsky date: Sat Aug 22 21:22:28 2015 -0400 summary: PEP 495: Are two values enough? // Backward Compatibility files: pep-0495.txt | 49 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 48 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -499,7 +499,50 @@ Are two values enough? ---------------------------------------- +---------------------- + +Several reasons have been raised to allow a ``None`` or -1 value for +the ``first`` flag: backward compatibility, analogy with ``tm_isdst`` +and strict checking for invalid times. + + +Backward Compatibility +...................... + +This PEP provides only three ways for a program to discover that two +otherwise identical datetime instances have different values of +``first``: (1) an explicit check of the ``first`` attribute; (2) if +the instances are naive - conversion to another timezone using the +``astimezone()`` method; and (3) conversion to ``float`` using the +``timestamp()`` method. + +Since ``first`` is a new attribute, the first option is not available +to the existing programs. Note that option (2) only works for naive +datetimes that happen to be in a fold or a gap in the system time +zone. In all other cases, the value of ``first`` will be ignored in +the conversion unless the instances use a ``first``-aware ``tzinfo`` +which would not be available in a pre-PEP program. Similarly, the +``astimezone()`` called on a naive instance will not be available in +such program because ``astimezone()`` does not currently work with +naive datetimes. + +This leaves us with only one situation where an existing program can +start producing diferent results after the implementation of this PEP: +when a ``datetime.timestamp()`` method is called on a naive datetime +instance that happen to be in the fold or the gap. In the current +implementation, the result is undefined. Depending on the system +``mktime`` implementation, the programs can see different results or +errors in those cases. With this PEP in place, the value of timestamp +will be well-defined in those cases but will depend on the value of +the ``first`` flag. We consider the change in +``datetime.timestamp()`` method behavior a bug fix enabled by this +PEP. The old behavior can still be emulated by the users who depend +on it by writing ``time.mktime(dt.timetuple()) + 1e-6*dt.microsecond`` +instead of ``dt.timestamp()``. + + +Analogy with tm_isdst +..................... The ``time.mktime`` interface allows three values for the ``tm_isdst`` flag: -1, 0, and 1. As we explained above, -1 (asking ``mktime`` to @@ -564,6 +607,10 @@ old behavior except in the few cases where the old behavior was undefined. + +Strict Invalid Time Checking +............................ + Another suggestion was to use ``first=-1`` or ``first=None`` to indicate that the program truly has no means to deal with the folds and gaps and ``dt.utcoffset()`` should raise an error whenever ``dt`` -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 04:39:05 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 23 Aug 2015 02:39:05 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_named_field_attrs?= =?utf-8?q?=2C_update_keyword_arg_discussion?= Message-ID: <20150823023905.19648.96591@psf.io> https://hg.python.org/peps/rev/42e6bc86ca5e changeset: 5978:42e6bc86ca5e user: Nick Coghlan date: Sun Aug 23 07:34:57 2015 +1000 summary: PEP 501: named field attrs, update keyword arg discussion files: pep-0501.txt | 85 +++++++++++++++++++++++++-------------- 1 files changed, 55 insertions(+), 30 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -43,6 +43,7 @@ myquery = sql$"SELECT $column FROM $table;" mycommand = sh$"cat $filename" mypage = html$"${response.body}" + callable = defer$ "$x + $y" Proposal ======== @@ -101,11 +102,11 @@ expressions into Python, when we already have 3 (``str.format``, ``bytes.__mod__`` and ``string.Template``) -This PEP proposes to handle the latter issue by always specifying an explicit -interpolator for interpolation operations, and the former by adopting the +This PEP proposes to handle the former issue by always specifying an explicit +interpolator for interpolation operations, and the latter by adopting the ``string.Template`` substitution syntax defined in PEP 292. -The interpolation syntax devised for PEP 292 is deliberately simple so that the +The substitution syntax devised for PEP 292 is deliberately simple so that the template strings can be extracted into an i18n message catalog, and passed to translators who may not themselves be developers. For these use cases, it is important that the interpolation syntax be as simple as possible, as the @@ -120,7 +121,7 @@ tools the option of rejecting usage of that more advanced syntax at runtime, rather than categorically rejecting it at compile time. The proposed permitted expressions, conversion specifiers, and format specifiers inside ``${ref}`` are -exactly as defined in PEP 498. +exactly as defined for ``{ref}`` substituion in PEP 498. The specific proposal in this PEP is also deliberately close in both syntax and semantics to the general purpose interpolation syntax introduced to @@ -156,7 +157,7 @@ These components are then organised into a tuple of tuples, and passed to the ``__interpolate__`` method of the interpolator identified by the given -name:: +name along with the runtime values of any expressions to be interpolated:: DOTTED_NAME.__interpolate__(TEMPLATE_STRING, , @@ -172,15 +173,29 @@ * the substitution conversion specifier (as defined by str.format) * the substitution format specifier (as defined by str.format) -If a given substition field has no leading literal section, format specifier -or conversion specifier, then the corresponding elements in the tuple are the +This field ordering is defined such that reading the parsed field tuples from +left to right will have all the subcomponents displayed in the same order as +they appear in the original template string. + +For ease of access the sequence elements will be available as attributes in +addition to being available by position: + +* ``leading_text`` +* ``field_position`` +* ``expression`` +* ``conversion`` +* ``format`` + +The expression text is simply the text of the substitution expression, as it +appeared in the original string, but without the leading and/or surrounding +expression markers. The conversion specifier and format specifier are separated +from the substition expression by ``!`` and ``:`` as defined for ``str.format``. + +If a given substition field has no leading literal section, coversion specifier +or format specifier, then the corresponding elements in the tuple are the empty string. If the final part of the string has no trailing substitution -field, then the field number, format specifier -and conversion specifier will all be ``None``. - -The expression text is simply the text of each interpolated expression, as it -appeared in the original string, but without the leading and/or surrounding -expression markers. +field, then the field position, field expression, conversion specifier and +format specifier will all be ``None``. The substitution field values tuple is created by evaluating the interpolated expressions in the exact runtime context where the interpolation expression @@ -360,9 +375,10 @@ And would could then be invoked as:: + # _ = i18n at top of module or injected into the builtins module print(_$"This is a $translated $message") -Any actual implementation would need to address other issues (most notably +Any actual i18n implementation would need to address other issues (most notably message catalog extraction), but this gives the general idea of what might be possible. @@ -406,6 +422,28 @@ Refer to PEP 498 for additional discussion, as several of the points there also apply to this PEP. +Using call syntax to support keyword-only parameters +---------------------------------------------------- + +The logging examples raise the question of whether or not it may be desirable +to allow interpolators to accept arbitrary keyword arguments, and allow folks +to write things like:: + + logging.critical$"Error: $error; Details: $data"(exc_info=True) + +in order to pass additional keyword only arguments to the interpolator. + +With the current PEP, such code would attempt to call the result of the +interpolation operation. If interpolation keyword support was added, then +calling the result of an interpolation operation directly would require +parentheses for disambiguation:: + + (defer$ "$x + $y")() + +("defer" here would be an interpolator that compiled the supplied string as +a piece of Python code with eagerly bound references to the containing +namespace) + Determining relative precedence ------------------------------- @@ -457,22 +495,9 @@ has other differences (like including both the field position number *and* the text of the expression). -Using call syntax to support keyword-only parameters ----------------------------------------------------- - -The logging examples could potentially be better written as:: - - !logging.debug("Event: $event; Details: $data") - !logging.critical("Error: $error; Details: $data") - -The key benefit this would provide is access to keyword arguments, so you -could write: - - !logging.critical("Error: $error; Details: $data", exc_info=True) - -In this version, an interpolation expression would largely be syntactically -equivalent to a normal function call, except that it would be restricted to -accepting a single string literal as its sole position argument. +This PEP also makes the parsed field attributes available by name, so it's +possible to write interpolators without caring about the precise field order +at all. References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 04:39:05 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 23 Aug 2015 02:39:05 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_string_prefix_redu?= =?utf-8?q?x=2C_now_with_template_objects?= Message-ID: <20150823023905.27301.27565@psf.io> https://hg.python.org/peps/rev/709fd2bc3720 changeset: 5979:709fd2bc3720 user: Nick Coghlan date: Sun Aug 23 12:38:55 2015 +1000 summary: PEP 501: string prefix redux, now with template objects files: pep-0501.txt | 264 +++++++++++++++++++------------------- 1 files changed, 135 insertions(+), 129 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -29,29 +29,39 @@ has not been properly escaped before being passed to the ``os.system`` call. To address that problem (and a number of other concerns), this PEP proposes an -alternative approach to compiler supported interpolation, based on a new ``$`` -binary operator with a syntactically constrained right hand side, a new -``__interpolate__`` magic method, and a substitution syntax inspired by -that used in ``string.Template`` and ES6 JavaScript, rather than adding a 4th -substitution variable syntax to Python. +alternative approach to compiler supported interpolation, using ``i`` (for +"interpolation") as the new string prefix and a substitution syntax +inspired by that used in ``string.Template`` and ES6 JavaScript, rather than +adding a 4th substitution variable syntax to Python. -Some examples of the proposed syntax:: +Some possible examples of the proposed syntax:: - msg = str$'My age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' - print(_$"This is a $translated $message") - translated = l20n$"{{ $user }} is running {{ appname }}" - myquery = sql$"SELECT $column FROM $table;" - mycommand = sh$"cat $filename" - mypage = html$"${response.body}" - callable = defer$ "$x + $y" + msg = str(i'My age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.') + print(_(i"This is a $translated $message")) + translated = l20n(i"{{ $user }} is running {{ appname }}") + myquery = sql(i"SELECT $column FROM $table;") + mycommand = sh(i"cat $filename") + mypage = html(i"${response.body}") + callable = defer(i"$x + $y") + +Summary of differences from PEP 498 +=================================== + +The key differences of this proposal relative to PEP 498: + +* "i" (interpolation template) prefix rather than "f" (formatted string) +* string.Template/JavaScript inspired substitution syntax, rather than str.format/C# inspired +* interpolation templates are created at runtime as a new kind of object +* the default rendering is invoked by calling ``str()`` on a template object + rather than automatically Proposal ======== -This PEP proposes the introduction of a new binary operator specifically for -interpolation of arbitrary expressions:: +This PEP proposes the introduction of a new string prefix that declares the +string to be an interpolation template rather than an ordinary string:: - value = interpolator $ "Substitute $names and ${expressions} at runtime" + template = $"Substitute $names and ${expressions} at runtime" This would be effectively interpreted as:: @@ -62,28 +72,25 @@ (" at runtime", None, None, None, None), ) _field_values = (names, expressions) - value = interpolator.__interpolate__(_raw_template, - _parsed_fields, - _field_values) + template = types.InterpolationTemplate(_raw_template, + _parsed_fields, + _field_values) -The right hand side of the new operator would be syntactically constrained to -be a string literal. - -The ``str`` builtin type would gain an ``__interpolate__`` implementation that -supported the following ``str.format`` inspired semantics:: +The ``__str__`` method on ``types.InterpolationTemplate`` would then implementat +the following ``str.format`` inspired semantics:: >>> import datetime >>> name = 'Jane' >>> age = 50 >>> anniversary = datetime.date(1991, 10, 12) - >>> str$'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.' + >>> str(i'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.') 'My name is Jane, my age next year is 51, my anniversary is Saturday, October 12, 1991.' - >>> str$'She said her name is ${name!r}.' + >>> str(i'She said her name is ${name!r}.') "She said her name is 'Jane'." -The interpolation operator could be used with single-quoted, double-quoted and -triple quoted strings, including raw strings. It would not support bytes -literals as the right hand side of the expression. +The interpolation template prefix can be combined with single-quoted, +double-quoted and triple quoted strings, including raw strings. It does not +support combination with bytes literals. This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms, as those will remain valuable when formatting @@ -102,9 +109,11 @@ expressions into Python, when we already have 3 (``str.format``, ``bytes.__mod__`` and ``string.Template``) -This PEP proposes to handle the former issue by always specifying an explicit -interpolator for interpolation operations, and the latter by adopting the -``string.Template`` substitution syntax defined in PEP 292. +This PEP proposes to handle the former issue by deferring the actual rendering +of the interpolation template to its ``__str__`` method (allow the use of +other template renderers by passing the template around as an object), and the +latter by adopting the ``string.Template`` substitution syntax defined in PEP +292. The substitution syntax devised for PEP 292 is deliberately simple so that the template strings can be extracted into an i18n message catalog, and passed to @@ -133,18 +142,13 @@ Specification ============= -This PEP proposes the introduction of ``$`` as a new binary operator designed -specifically to support interpolation of template strings:: +This PEP proposes the introduction of ``i`` as a new string prefix that +results in the creation of an instance of a new type, +``types.InterpolationTemplate``. - INTERPOLATOR $ TEMPLATE_STRING - -This would work as a normal binary operator (precedence TBD), with the -exception that the template string would be syntactically constrained to be a -string literal, rather than permitting arbitrary expressions. - -The template string must be a Unicode string (bytes literals are not permitted), -and string literal concatenation operates as normal within the template string -component of the expression. +Interpolation template literals are Unicode strings (bytes literals are not +permitted), and string literal concatenation operates as normal, with the +entire combined literal forming the interpolation template. The template string is parsed into literals and expressions. Expressions appear as either identifiers prefixed with a single "$" character, or @@ -155,15 +159,37 @@ and is considered part of the literal text, rather than as introducing an expression. -These components are then organised into a tuple of tuples, and passed to the -``__interpolate__`` method of the interpolator identified by the given -name along with the runtime values of any expressions to be interpolated:: +These components are then organised into an instance of a new type with the +following semantics:: - DOTTED_NAME.__interpolate__(TEMPLATE_STRING, - , - ) + class InterpolationTemplate: + __slots__ = ("raw_template", "parsed_fields", "field_values") -The template string field tuple is inspired by the interface of + def __new__(cls, raw_template, parsed_fields, field_values): + self = super().__new__() + self.raw_template = raw_template + self.parsed_fields = parsed_fields + self.field_values = field_values + return self + + def __iter__(self): + # Support iterable unpacking + yield self.raw_template + yield self.parsed_fields + yield self.field_values + + def __repr__(self): + return str(i"<${type(self).__qualname__} ${self.raw_template!r} " + "at ${id(self):#x}>") + + def __str__(self): + # See definition of the default template rendering below + +The result of the interpolation template expression is an instance of this +type, rather than an already rendered string - default rendering only takes +place when the instance's ``__str__`` method is called. + +The format of the parsed fields tuple is inspired by the interface of ``string.Formatter.parse``, and consists of a series of 5-tuples each containing: @@ -191,7 +217,7 @@ expression markers. The conversion specifier and format specifier are separated from the substition expression by ``!`` and ``:`` as defined for ``str.format``. -If a given substition field has no leading literal section, coversion specifier +If a given substition field has no leading literal section, conversion specifier or format specifier, then the corresponding elements in the tuple are the empty string. If the final part of the string has no trailing substitution field, then the field position, field expression, conversion specifier and @@ -222,13 +248,14 @@ The parsed fields tuple can be constant folded at compile time, while the expression values tuple will always need to be constructed at runtime. -The ``str.__interpolate__`` implementation would have the following +The ``InterpolationTemplate.__str__`` implementation would have the following semantics, with field processing being defined in terms of the ``format`` builtin and ``str.format`` conversion specifiers:: _converter = string.Formatter().convert_field - def __interpolate__(raw_template, fields, values): + def __str__(self): + raw_template, fields, values = self template_parts = [] for leading_text, field_num, expr, conversion, format_spec in fields: template_parts.append(leading_text) @@ -243,18 +270,10 @@ Writing custom interpolators ---------------------------- -To simplify the process of writing custom interpolators, it is proposed to add -a new builtin decorator, ``interpolator``, which would be defined as:: - - def interpolator(f): - f.__interpolate__ = f.__call__ - return f - -This allows new interpolators to be written as:: - - @interpolator - def my_custom_interpolator(raw_template, parsed_fields, field_values): - ... +Writing a custom interpolator doesn't requiring any special syntax. Instead, +custom interpolators are ordinary callables that process an interpolation +template directly based on the ``raw_template``, ``parsed_fields`` and +``field_values`` attributes, rather than relying on the default rendered. Expression evaluation @@ -287,12 +306,12 @@ Handling code injection attacks ------------------------------- -The proposed interpolation expressions make it potentially attractive to write +The proposed interpolation syntax makes it potentially attractive to write code like the following:: - myquery = str$"SELECT $column FROM $table;" - mycommand = str$"cat $filename" - mypage = str$"${response.body}" + myquery = str(i"SELECT $column FROM $table;") + mycommand = str(i"cat $filename") + mypage = str(i"${response.body}") These all represent potential vectors for code injection attacks, if any of the variables being interpolated happen to come from an untrusted source. The @@ -300,15 +319,16 @@ use case specific interpolators that take care of quoting interpolated values appropriately for the relevant security context:: - myquery = sql$"SELECT $column FROM $table;" - mycommand = sh$"cat $filename" - mypage = html$"${response.body}" + myquery = sql(i"SELECT $column FROM $table;") + mycommand = sh(i"cat $filename") + mypage = html(i"${response.body}") This PEP does not cover adding such interpolators to the standard library, but instead ensures they can be readily provided by third party libraries. -(Although it's tempting to propose adding __interpolate__ implementations to -``subprocess.call``, ``subprocess.check_call`` and ``subprocess.check_output``) +(Although it's tempting to propose adding InterpolationTemplate support at +least to ``subprocess.call``, ``subprocess.check_call`` and +``subprocess.check_output``) Format and conversion specifiers -------------------------------- @@ -328,20 +348,21 @@ Unmatched braces:: - >>> str$'x=${x' + >>> i'x=${x' File "", line 1 SyntaxError: missing '}' in interpolation expression Invalid expressions:: - >>> str$'x=${!x}' + >>> i'x=${!x}' File "", line 1 !x ^ SyntaxError: invalid syntax -Run time errors occur when evaluating the expressions inside an -template string. See PEP 498 for some examples. +Run time errors occur when evaluating the expressions inside a +template string before creating the interpolation template object. See PEP 498 +for some examples. Different interpolators may also impose additional runtime constraints on acceptable interpolated expressions and other formatting @@ -359,9 +380,10 @@ performs internationalisation. For example, the following implementation would delegate interpolation calls to ``string.Template``:: - @interpolator - def i18n(template, fields, values): - translated = gettext.gettext(template) + def i18n(template): + # A real implementation would also handle normal strings + raw_template, fields, values = template + translated = gettext.gettext(raw_template) value_map = _build_interpolation_map(fields, values) return string.Template(translated).safe_substitute(value_map) @@ -376,7 +398,7 @@ And would could then be invoked as:: # _ = i18n at top of module or injected into the builtins module - print(_$"This is a $translated $message") + print(_(i"This is a $translated $message")) Any actual i18n implementation would need to address other issues (most notably message catalog extraction), but this gives the general idea of what might be @@ -389,14 +411,14 @@ With the syntax in this PEP, an l20n interpolator could be written as:: - translated = l20n$"{{ $user }} is running {{ appname }}" + translated = l20n(i"{{ $user }} is running {{ appname }}") With the syntax proposed in PEP 498 (and neglecting the difficulty of doing catalog lookups using PEP 498's semantics), the necessary brace escaping would make the string look like this in order to interpolate the user variable while preserving all of the expected braces:: - interpolated = "{{{{ ${user} }}}} is running {{{{ appname }}}}" + locally_interpolated = f"{{{{ ${user} }}}} is running {{{{ appname }}}}" Possible integration with the logging module @@ -408,13 +430,17 @@ logging messages also poses a problem for extensive logging of runtime events for monitoring purposes. -While beyond the scope of this initial PEP, the proposal described here could -potentially be applied to the logging module's event reporting APIs, permitting -relevant details to be captured using forms like:: +While beyond the scope of this initial PEP, interpolation template support +could potentially be added to the logging module's event reporting APIs, +permitting relevant details to be captured using forms like:: - logging.debug$"Event: $event; Details: $data" - logging.critical$"Error: $error; Details: $data" + logging.debug(i"Event: $event; Details: $data") + logging.critical(i"Error: $error; Details: $data") +As the interpolation template is passed in as an ordinary argument, other +keyword arguments also remain available:: + + logging.critical(i"Error: $error; Details: $data", exc_info=True) Discussion ========== @@ -422,45 +448,14 @@ Refer to PEP 498 for additional discussion, as several of the points there also apply to this PEP. -Using call syntax to support keyword-only parameters ----------------------------------------------------- - -The logging examples raise the question of whether or not it may be desirable -to allow interpolators to accept arbitrary keyword arguments, and allow folks -to write things like:: - - logging.critical$"Error: $error; Details: $data"(exc_info=True) - -in order to pass additional keyword only arguments to the interpolator. - -With the current PEP, such code would attempt to call the result of the -interpolation operation. If interpolation keyword support was added, then -calling the result of an interpolation operation directly would require -parentheses for disambiguation:: - - (defer$ "$x + $y")() - -("defer" here would be an interpolator that compiled the supplied string as -a piece of Python code with eagerly bound references to the containing -namespace) - -Determining relative precedence -------------------------------- - -The PEP doesn't currently specify the relative precedence of the new operator, -as the only examples considered so far concern standalone expressions or simple -variable assignments. - -Development of a reference implementation based on the PEP 498 reference -implementation may help answer that question. - Deferring support for binary interpolation ------------------------------------------ Supporting binary interpolation with this syntax would be relatively -straightforward (just a matter of relaxing the syntactic restrictions on the -right hand side of the operator), but poses a signficant likelihood of -producing confusing type errors when a text interpolator was presented with +straightforward (the elements in the parsed fields tuple would just be +byte strings rather than text strings, and the default renderer would be +markedly less useful), but poses a signficant likelihood of producing +confusing type errors when a text interpolator was presented with binary input. Since the proposed operator is useful without binary interpolation support, and @@ -474,13 +469,13 @@ to interpolators. This greatly complicated the i18n example, as it needed to reconstruct the original template to pass to the message catalog lookup. -Using a magic method rather than a global name lookup ------------------------------------------------------ +Creating a rich object rather than a global name lookup +------------------------------------------------------- Earlier versions of this PEP used an ``__interpolate__`` builtin, rather than -a magic method on an explicitly named interpolator. Naming the interpolator -eliminated a lot of the complexity otherwise associated with shadowing the -builtin function in order to modify the semantics of interpolation. +a creating a new kind of object for later consumption by interpolation +functions. Creating a rich descriptive object with a useful default renderer +made it much easier to support customisation of the semantics of interpolation. Relative order of conversion and format specifier in parsed fields ------------------------------------------------------------------ @@ -499,6 +494,17 @@ possible to write interpolators without caring about the precise field order at all. + +Acknowledgements +================ + +* Eric V. Smith for creating PEP 498 and demonstrating the feasibility of + arbitrary expression substitution in string interpolation +* Barry Warsaw for the string.Template syntax defined in PEP 292 +* Armin Ronacher for pointing me towards Mozilla's l20n project +* Mike Miller for his survey of programming language interpolation syntaxes in + PEP (TBD) + References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 04:41:37 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 23 Aug 2015 02:41:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_Add_a_new_post_dat?= =?utf-8?q?e_for_this_version?= Message-ID: <20150823024137.21445.59280@psf.io> https://hg.python.org/peps/rev/23d6ac4b33fc changeset: 5980:23d6ac4b33fc user: Nick Coghlan date: Sun Aug 23 12:41:30 2015 +1000 summary: PEP 501: Add a new post date for this version files: pep-0501.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 08-Aug-2015 Python-Version: 3.6 -Post-History: 08-Aug-2015 +Post-History: 08-Aug-2015, 23-Aug-2015 Abstract ======== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 05:44:54 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 23 Aug 2015 03:44:54 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_remove_remnants_of?= =?utf-8?q?_previous_iteration?= Message-ID: <20150823034454.29368.49326@psf.io> https://hg.python.org/peps/rev/e43862f323d8 changeset: 5981:e43862f323d8 user: Nick Coghlan date: Sun Aug 23 13:44:47 2015 +1000 summary: PEP 501: remove remnants of previous iteration files: pep-0501.txt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -61,7 +61,7 @@ This PEP proposes the introduction of a new string prefix that declares the string to be an interpolation template rather than an ordinary string:: - template = $"Substitute $names and ${expressions} at runtime" + template = i"Substitute $names and ${expressions} at runtime" This would be effectively interpreted as:: @@ -227,9 +227,9 @@ expressions in the exact runtime context where the interpolation expression appears in the source code. -For the following example interpolation expression:: +For the following example interpolation template:: - str$'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl' + i'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl' the parsed fields tuple would be:: @@ -295,7 +295,7 @@ >>> def foo(data): ... return data + 20 ... - >>> str$'input=$bar, output=${foo(bar)}' + >>> str(i'input=$bar, output=${foo(bar)}') 'input=10, output=30' Is essentially equivalent to:: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 06:18:02 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 23 Aug 2015 04:18:02 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_Explicit_note_rega?= =?utf-8?q?rding_prerendering_templates?= Message-ID: <20150823041802.21449.15548@psf.io> https://hg.python.org/peps/rev/331fbc7ada74 changeset: 5982:331fbc7ada74 user: Nick Coghlan date: Sun Aug 23 14:17:45 2015 +1000 summary: PEP 501: Explicit note regarding prerendering templates files: pep-0501.txt | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -462,6 +462,17 @@ such support can be readily added later, further consideration of binary interpolation is considered out of scope for the current PEP. +Interoperability with str-only interfaces +----------------------------------------- + +For interoperability with interfaces that only accept strings, interpolation +templates can be prerendered with ``str``, rather than delegating the rendering +to the called function. + +This reflects the key difference from PEP 498, which *always* eagerly applies] +the default rendering, without any convenient way to decide to do something +different. + Preserving the raw template string ---------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 23 20:28:07 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 23 Aug 2015 18:28:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324878=3A_Fix_typo?= =?utf-8?q?s_and_line_wrap?= Message-ID: <20150823182807.12127.44973@psf.io> https://hg.python.org/cpython/rev/4432c441b639 changeset: 97464:4432c441b639 user: Raymond Hettinger date: Sun Aug 23 11:28:01 2015 -0700 summary: Issue #24878: Fix typos and line wrap files: Lib/aifc.py | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -258,12 +258,13 @@ 'nchannels sampwidth framerate nframes comptype compname') _aifc_params.nchannels.__doc__ = 'Number of audio channels (1 for mono, 2 for stereo)' -_aifc_params.sampwidth.__doc__ = 'Ample width in bytes' +_aifc_params.sampwidth.__doc__ = 'Sample width in bytes' _aifc_params.framerate.__doc__ = 'Sampling frequency' _aifc_params.nframes.__doc__ = 'Number of audio frames' _aifc_params.comptype.__doc__ = 'Compression type ("NONE" for AIFF files)' -_aifc_params.compname.__doc__ = ("""A human-readable version ofcompression type -('not compressed' for AIFF files)'""") +_aifc_params.compname.__doc__ = ("""\ +A human-readable version of the compression type +('not compressed' for AIFF files)""") class Aifc_read: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 01:47:14 2015 From: python-checkins at python.org (robert.collins) Date: Sun, 23 Aug 2015 23:47:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324633=3A_site-pac?= =?utf-8?q?kages/README_-=3E_README=2Etxt=2E?= Message-ID: <20150823234713.79927.44613@psf.io> https://hg.python.org/cpython/rev/d90a65014c42 changeset: 97465:d90a65014c42 user: Robert Collins date: Mon Aug 24 11:46:56 2015 +1200 summary: Issue #24633: site-packages/README -> README.txt. files: Lib/site-packages/README.txt | 0 Misc/NEWS | 2 ++ 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/site-packages/README b/Lib/site-packages/README.txt rename from Lib/site-packages/README rename to Lib/site-packages/README.txt diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Library ------- +- Issue #24633: site-packages/README -> README.txt. + - Issue #20362: Honour TestCase.longMessage correctly in assertRegex. Patch from Ilia Kurenkov. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 02:10:57 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 24 Aug 2015 00:10:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyODEy?= =?utf-8?q?=3A_Fix_unittest_discovery_examples=2E?= Message-ID: <20150824001057.12145.68479@psf.io> https://hg.python.org/cpython/rev/3256764fadae changeset: 97466:3256764fadae branch: 2.7 parent: 97301:08e03dfb7dab user: Robert Collins date: Mon Aug 24 12:06:18 2015 +1200 summary: Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. files: Doc/library/unittest.rst | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -286,8 +286,8 @@ as positional arguments in that order. The following two command lines are equivalent:: - python -m unittest discover -s project_directory -p '*_test.py' - python -m unittest discover project_directory '*_test.py' + python -m unittest discover -s project_directory -p "*_test.py" + python -m unittest discover project_directory "*_test.py" As well as being a path it is possible to pass a package name, for example ``myproject.subpackage.test``, as the start directory. The package name you diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -880,6 +880,7 @@ Madison May Lucas Maystre Arnaud Mazin +Pam McA'Nulty Matt McClure Rebecca McCreary Kirk McDonald diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #22812: Fix unittest discovery examples. + Patch from Pam McA'Nulty. + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Initial patch by Matt Frank. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 02:10:57 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 24 Aug 2015 00:10:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Merge_2=2E7_heads=2E?= Message-ID: <20150824001057.27321.38842@psf.io> https://hg.python.org/cpython/rev/61b77bdfbc54 changeset: 97467:61b77bdfbc54 branch: 2.7 parent: 97466:3256764fadae parent: 97462:ea2f6fd04307 user: Robert Collins date: Mon Aug 24 12:10:23 2015 +1200 summary: Merge 2.7 heads. files: Doc/library/xml.etree.elementtree.rst | 30 +- Include/pymath.h | 24 +- Lib/distutils/msvc9compiler.py | 2 +- Lib/idlelib/NEWS.txt | 26 +- Lib/idlelib/ScriptBinding.py | 2 +- Lib/idlelib/StackViewer.py | 10 +- Lib/test/regrtest.py | 14 +- Lib/uuid.py | 8 +- Misc/ACKS | 2 + Misc/NEWS | 71 +- Parser/tokenizer.c | 5 +- Python/ceval.c | 346 +++++++------- 12 files changed, 307 insertions(+), 233 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -600,21 +600,29 @@ .. attribute:: text + tail - The *text* attribute can be used to hold additional data associated with - the element. As the name implies this attribute is usually a string but - may be any application-specific object. If the element is created from - an XML file the attribute will contain any text found between the element - tags. + These attributes can be used to hold additional data associated with + the element. Their values are usually strings but may be any + application-specific object. If the element is created from + an XML file, the *text* attribute holds either the text between + the element's start tag and its first child or end tag, or ``None``, and + the *tail* attribute holds either the text between the element's + end tag and the next tag, or ``None``. For the XML data + .. code-block:: xml - .. attribute:: tail + 1234 - The *tail* attribute can be used to hold additional data associated with - the element. This attribute is usually a string but may be any - application-specific object. If the element is created from an XML file - the attribute will contain any text found after the element's end tag and - before the next tag. + the *a* element has ``None`` for both *text* and *tail* attributes, + the *b* element has *text* ``"1"`` and *tail* ``"4"``, + the *c* element has *text* ``"2"`` and *tail* ``None``, + and the *d* element has *text* ``None`` and *tail* ``"3"``. + + To collect the inner text of an element, see :meth:`itertext`, for + example ``"".join(element.itertext())``. + + Applications may store arbitrary objects in these attributes. .. attribute:: attrib diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -152,7 +152,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -426,7 +426,7 @@ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] if self.__version >= 7: self.ldflags_shared_debug = [ - '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None' + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' ] self.ldflags_static = [ '/nologo'] diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,7 +1,29 @@ +What's New in IDLE 2.7.11? +========================= + +*Release date: + +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + +- Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for + decoding unicode literals. + + What's New in IDLE 2.7.10? ========================= -*Release data: 2015-05-23* +*Release date: 2015-05-23* - Issue #23583: Fixed writing unicode to standard output stream in IDLE. @@ -20,7 +42,7 @@ What's New in IDLE 2.7.9? ========================= -*Release data: 2014-12-10* +*Release date: 2014-12-10* - Issue #16893: Update Idle doc chapter to match current Idle and add new information. diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -71,7 +71,7 @@ try: tabnanny.process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError as msg: - msgtxt, (lineno, start) = msg + msgtxt, (lineno, start) = msg.args self.editwin.gotoline(lineno) self.errorbox("Tabnanny Tokenizing Error", "Token Error: %s" % msgtxt) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -10,8 +10,7 @@ def StackBrowser(root, flist=None, tb=None, top=None): if top is None: - from Tkinter import Toplevel - top = Toplevel(root) + top = tk.Toplevel(root) sc = ScrolledCanvas(top, bg="white", highlightthickness=0) sc.frame.pack(expand=1, fill="both") item = StackTreeItem(flist, tb) @@ -108,12 +107,9 @@ def IsExpandable(self): return len(self.object) > 0 - def keys(self): - return self.object.keys() - def GetSubList(self): sublist = [] - for key in self.keys(): + for key in self.object.keys(): try: value = self.object[key] except KeyError: @@ -124,7 +120,7 @@ sublist.append(item) return sublist -def _stack_viewer(parent): +def _stack_viewer(parent): # htest # root = tk.Tk() root.title("Test StackViewer") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -624,14 +624,12 @@ for time, test in test_times[:10]: print "%s: %.1fs" % (test, time) if bad: - bad = set(bad) - set(environment_changed) - if bad: - print count(len(bad), "test"), "failed:" - printlist(bad) - if environment_changed: - print "{} altered the execution environment:".format( - count(len(environment_changed), "test")) - printlist(environment_changed) + print count(len(bad), "test"), "failed:" + printlist(bad) + if environment_changed: + print "{} altered the execution environment:".format( + count(len(environment_changed), "test")) + printlist(environment_changed) if skipped and not quiet: print count(len(skipped), "test"), "skipped:" printlist(skipped) diff --git a/Lib/uuid.py b/Lib/uuid.py --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -441,10 +441,14 @@ _uuid_generate_random = _uuid_generate_time = _UuidCreate = None try: import ctypes, ctypes.util + import sys # The uuid_generate_* routines are provided by libuuid on at least # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: + _libnames = ['uuid'] + if not sys.platform.startswith('win'): + _libnames.append('c') + for libname in _libnames: try: lib = ctypes.CDLL(ctypes.util.find_library(libname)) except: @@ -455,6 +459,7 @@ _uuid_generate_time = lib.uuid_generate_time if _uuid_generate_random is not None: break # found everything we were looking for + del _libnames # The uuid_generate_* functions are broken on MacOS X 10.5, as noted # in issue #8621 the function generates the same sequence of values @@ -463,7 +468,6 @@ # # Assume that the uuid_generate functions are broken from 10.5 onward, # the test can be adjusted when a later version is fixed. - import sys if sys.platform == 'darwin': import os if int(os.uname()[2].split('.')[0]) >= 9: diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -573,6 +573,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda @@ -1139,6 +1140,7 @@ Wes Rishel Daniel Riti Juan M. Bello Rivas +Mohd Sanad Zaki Rizvi Davide Rizzo Anthony Roach Carl Robben diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + - Issue #24467: Fixed possible buffer over-read in bytearray. The bytearray object now always allocates place for trailing null byte and it's buffer now is always null-terminated. @@ -37,6 +40,8 @@ - Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. +- Issue #24634: Importing uuid should not try to load libc on Windows + - Issue #23652: Make it possible to compile the select module against the libc headers from the Linux Standard Base, which do not include some EPOLL macros. Initial patch by Matt Frank. @@ -100,7 +105,7 @@ - Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked cursor type. -- Issue #24286: Dict view were not registered with the MappingView abstract +- Issue #24286: Dict view were not registered with the MappingView abstract base classes. This caused key and item views in OrderedDict to not be equal to their regular dict counterparts. @@ -139,6 +144,19 @@ IDLE ---- +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. + - Issue #15809: IDLE shell now uses locale encoding instead of Latin1 for decoding unicode literals. @@ -179,9 +197,9 @@ Core and Builtins ----------------- -- Issue #23971: Fix underestimated presizing in dict.fromkeys(). - -- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API +- Issue #23971: Fix underestimated presizing in dict.fromkeys(). + +- Issue #23757: PySequence_Tuple() incorrectly called the concrete list API when the data was a list subclass. - Issue #23629: Fix the default __sizeof__ implementation for variable-sized @@ -772,7 +790,7 @@ - Issue #16233: A module browser (File : Class Browser, Alt+C) requires a editor window with a filename. When Class Browser is requested otherwise, from a shell, output window, or 'Untitled' editor, Idle no longer displays - an error box. It now pops up an Open Module box (Alt+M). If a valid name + an error box. It now pops up an Open Module box (Alt+M). If a valid name is entered and a module is opened, a corresponding browser is also opened. - Issue #4832: Save As to type Python files automatically adds .py to the @@ -910,18 +928,18 @@ - Issue #21672: Fix the behavior of ntpath.join on UNC-style paths. -- Issue #19145: The times argument for itertools.repeat now handles +- Issue #19145: The times argument for itertools.repeat now handles negative values the same way for keyword arguments as it does for positional arguments. -- Issue #21832: Require named tuple inputs to be exact strings. - -- Issue #8343: Named group error messages in the re module did not show +- Issue #21832: Require named tuple inputs to be exact strings. + +- Issue #8343: Named group error messages in the re module did not show the name of the erroneous group. - Issue #21491: SocketServer: Fix a race condition in child processes reaping. -- Issue #21635: The difflib SequenceMatcher.get_matching_blocks() method +- Issue #21635: The difflib SequenceMatcher.get_matching_blocks() method cache didn't match the actual result. The former was a list of tuples and the latter was a list of named tuples. @@ -958,7 +976,7 @@ - Issue #8743: Fix interoperability between set objects and the collections.Set() abstract base class. -- Issue #21481: Argparse equality and inequality tests now return +- Issue #21481: Argparse equality and inequality tests now return NotImplemented when comparing to an unknown type. IDLE @@ -1100,7 +1118,7 @@ - Issue #21470: Do a better job seeding the random number generator by using enough bytes to span the full state space of the Mersenne Twister. -- Issue #21469: Reduced the risk of false positives in robotparser by +- Issue #21469: Reduced the risk of false positives in robotparser by checking to make sure that robots.txt has been read or does not exist prior to returning True in can_fetch(). @@ -1597,7 +1615,7 @@ - Issue #19131: The aifc module now correctly reads and writes sampwidth of compressed streams. -- Issue #19158: a rare race in BoundedSemaphore could allow .release() too +- Issue #19158: A rare race in BoundedSemaphore could allow .release() too often. - Issue #18037: 2to3 now escapes '\u' and '\U' in native strings. @@ -3598,7 +3616,7 @@ greater or equal to the default value, the value with which the interpreter was built. -- Issue #11802: The cache in filecmp now has a maximum size of 100 so that +- Issue #11802: The cache in filecmp now has a maximum size of 100 so that it won't grow without bound. - Issue #12404: Remove C89 incompatible code from mmap module. Patch by Akira @@ -3984,7 +4002,7 @@ - Issue #11277: mmap.mmap() calls fcntl(fd, F_FULLFSYNC) on Mac OS X to get around a mmap bug with sparse files. Patch written by Steffen Daode Nurpmeso. -- Issue #10761: Fix tarfile.extractall failure when symlinked files are +- Issue #10761: Fix tarfile.extractall failure when symlinked files are present. Initial patch by Scott Leerssen. - Issue #11763: don't use difflib in TestCase.assertMultiLineEqual if the @@ -4495,7 +4513,7 @@ - Issue #8530: Prevent stringlib fastsearch from reading beyond the front of an array. -- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe. +- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe. - Issue #9416: Fix some issues with complex formatting where the output with no type specifier failed to match the str output: @@ -4892,7 +4910,7 @@ os.getgroups() can now return more than 16 groups on MacOSX. - Issue #9277: Fix bug in struct.pack for bools in standard mode - (e.g., struct.pack('>?')): if conversion to bool raised an exception + (e.g., struct.pack('>?')): if conversion to bool raised an exception then that exception wasn't properly propagated on machines where char is unsigned. @@ -4940,7 +4958,7 @@ - Issue #9275: The OSX installer once again installs links to binaries in ``/usr/local/bin``. -- Issue #9392: A framework build on OSX will once again use a versioned name +- Issue #9392: A framework build on OSX will once again use a versioned name of the ``2to3`` tool, that is you can use ``2to3-2.7`` to select the Python 2.7 edition of 2to3. @@ -6899,7 +6917,7 @@ - Issue #6851: Fix urllib.urlopen crash on secondairy threads on OSX 10.6 -- Issue #4606: Passing 'None' if ctypes argtype is set to POINTER(...) does now +- Issue #4606: Passing 'None' if ctypes argtype is set to POINTER(...) does now always result in NULL. - Issue #5042: ctypes Structure sub-subclass does now initialize correctly with @@ -7744,7 +7762,7 @@ wasn't working with file paths containing spaces. - Issue #5783: Windows: Version string for the .chm help file changed, - file not being accessed Patch by Guilherme Polo/ + file not being accessed. Patch by Guilherme Polo/ - Issue #1529142: Allow multiple IDLE GUI/subprocess pairs to exist simultaneously. Thanks to David Scherer for suggesting the use of an @@ -8440,7 +8458,7 @@ - Issue #3437: Bug fix in robotparser parsing of Allow: lines. -- Issue #1592: Improve error reporting when operations are attempted +- Issue #1592: Improve error reporting when operations are attempted on a closed shelf. - Deprecate the "ast" parser function aliases. @@ -8662,7 +8680,7 @@ - Add future_builtins.ascii(). -- Several set methods now accept multiple arguments: update(), union(), +- Several set methods now accept multiple arguments: update(), union(), intersection(), intersection_update(), difference(), and difference_update(). - Issue #2898: Added sys.getsizeof() to retrieve size of objects in bytes. @@ -8698,7 +8716,7 @@ ----------------- - Issue #1179: [CVE-2007-4965] Integer overflow in imageop module. -- Issue #3116: marshal.dumps() had quadratic behavior for strings > 32Mb. +- Issue #3116: marshal.dumps() had quadratic behavior for strings > 32Mb. - Issue #2138: Add factorial() to the math module. @@ -9680,9 +9698,9 @@ - When __slots__ are set to a unicode string, make it work the same as setting a plain string, ie don't expand to single letter identifiers. -- Request #1191699: Slices can now be pickled. - -- Request #1193128: str.translate() now allows a None argument for +- Request #1191699: Slices can now be pickled. + +- Request #1193128: str.translate() now allows a None argument for translations that only remove characters without re-mapping the remaining characters. @@ -11201,3 +11219,4 @@ ---- **(For information about older versions, consult the HISTORY file.)** + diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -235,7 +235,10 @@ if (begin < t) { char* r = new_string(begin, t - begin); - char* q = get_normal_name(r); + char* q; + if (!r) + return NULL; + q = get_normal_name(r); if (r != q) { PyMem_FREE(r); r = new_string(q, strlen(q)); diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -709,73 +709,73 @@ /* This macro is used when several opcodes defer to the same implementation (e.g. SETUP_LOOP, SETUP_FINALLY) */ #define TARGET_WITH_IMPL(op, impl) \ - TARGET_##op: \ - opcode = op; \ - oparg = NEXTARG(); \ - case op: \ - goto impl; \ + TARGET_##op: \ + opcode = op; \ + oparg = NEXTARG(); \ + case op: \ + goto impl; \ #define TARGET_WITH_IMPL_NOARG(op, impl) \ - TARGET_##op: \ - opcode = op; \ - case op: \ - goto impl; \ + TARGET_##op: \ + opcode = op; \ + case op: \ + goto impl; \ #define TARGET_NOARG(op) \ - TARGET_##op: \ - opcode = op; \ - case op:\ + TARGET_##op: \ + opcode = op; \ + case op:\ #define TARGET(op) \ - TARGET_##op: \ - opcode = op; \ - oparg = NEXTARG(); \ - case op:\ + TARGET_##op: \ + opcode = op; \ + oparg = NEXTARG(); \ + case op:\ #define DISPATCH() \ - { \ - int _tick = _Py_Ticker - 1; \ - _Py_Ticker = _tick; \ - if (_tick >= 0) { \ - FAST_DISPATCH(); \ - } \ - continue; \ - } + { \ + int _tick = _Py_Ticker - 1; \ + _Py_Ticker = _tick; \ + if (_tick >= 0) { \ + FAST_DISPATCH(); \ + } \ + continue; \ + } #ifdef LLTRACE #define FAST_DISPATCH() \ - { \ - if (!lltrace && !_Py_TracingPossible) { \ - f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ - } \ - goto fast_next_opcode; \ - } + { \ + if (!lltrace && !_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode; \ + } #else #define FAST_DISPATCH() { \ - if (!_Py_TracingPossible) { \ - f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ - } \ - goto fast_next_opcode;\ + if (!_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode;\ } #endif #else #define TARGET(op) \ - case op: + case op: #define TARGET_WITH_IMPL(op, impl) \ - /* silence compiler warnings about `impl` unused */ \ - if (0) goto impl; \ - case op:\ + /* silence compiler warnings about `impl` unused */ \ + if (0) goto impl; \ + case op:\ #define TARGET_NOARG(op) \ - case op:\ + case op:\ #define TARGET_WITH_IMPL_NOARG(op, impl) \ - if (0) goto impl; \ - case op:\ + if (0) goto impl; \ + case op:\ #define DISPATCH() continue #define FAST_DISPATCH() goto fast_next_opcode @@ -1206,9 +1206,9 @@ /* case STOP_CODE: this is an error! */ TARGET_NOARG(NOP) - { - FAST_DISPATCH(); - } + { + FAST_DISPATCH(); + } TARGET(LOAD_FAST) { @@ -1216,7 +1216,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - FAST_DISPATCH(); + FAST_DISPATCH(); } format_exc_check_arg(PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, @@ -1229,7 +1229,7 @@ x = GETITEM(consts, oparg); Py_INCREF(x); PUSH(x); - FAST_DISPATCH(); + FAST_DISPATCH(); } PREDICTED_WITH_ARG(STORE_FAST); @@ -1237,14 +1237,14 @@ { v = POP(); SETLOCAL(oparg, v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(POP_TOP) { v = POP(); Py_DECREF(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(ROT_TWO) @@ -1253,7 +1253,7 @@ w = SECOND(); SET_TOP(w); SET_SECOND(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(ROT_THREE) @@ -1264,11 +1264,11 @@ SET_TOP(w); SET_SECOND(x); SET_THIRD(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } TARGET_NOARG(ROT_FOUR) - { + { u = TOP(); v = SECOND(); w = THIRD(); @@ -1278,7 +1278,7 @@ SET_THIRD(x); SET_FOURTH(u); FAST_DISPATCH(); - } + } TARGET_NOARG(DUP_TOP) @@ -1286,7 +1286,7 @@ v = TOP(); Py_INCREF(v); PUSH(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } @@ -1300,7 +1300,7 @@ STACKADJ(2); SET_TOP(x); SET_SECOND(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } else if (oparg == 3) { x = TOP(); Py_INCREF(x); @@ -1312,7 +1312,7 @@ SET_TOP(x); SET_SECOND(w); SET_THIRD(v); - FAST_DISPATCH(); + FAST_DISPATCH(); } Py_FatalError("invalid argument to DUP_TOPX" " (bytecode corruption?)"); @@ -1326,7 +1326,7 @@ x = PyNumber_Positive(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1336,7 +1336,7 @@ x = PyNumber_Negative(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1348,13 +1348,13 @@ if (err == 0) { Py_INCREF(Py_True); SET_TOP(Py_True); - DISPATCH(); + DISPATCH(); } else if (err > 0) { Py_INCREF(Py_False); SET_TOP(Py_False); err = 0; - DISPATCH(); + DISPATCH(); } STACKADJ(-1); break; @@ -1366,7 +1366,7 @@ x = PyObject_Repr(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1376,7 +1376,7 @@ x = PyNumber_Invert(v); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1388,7 +1388,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1400,7 +1400,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if(x!=NULL) DISPATCH(); + if(x!=NULL) DISPATCH(); break; } @@ -1413,7 +1413,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } } @@ -1426,7 +1426,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1438,7 +1438,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1453,7 +1453,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1487,7 +1487,7 @@ skip_decref_vx: Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1514,7 +1514,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1540,7 +1540,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1552,7 +1552,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1564,7 +1564,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1576,7 +1576,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1588,7 +1588,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1600,7 +1600,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1612,7 +1612,7 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - DISPATCH(); + DISPATCH(); } break; } @@ -1625,7 +1625,7 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - DISPATCH(); + DISPATCH(); } break; } @@ -1638,7 +1638,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1650,7 +1650,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1663,7 +1663,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } } @@ -1677,7 +1677,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1689,7 +1689,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1701,7 +1701,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1733,7 +1733,7 @@ skip_decref_v: Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1758,7 +1758,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1770,7 +1770,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1782,7 +1782,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1794,7 +1794,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1806,7 +1806,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1818,7 +1818,7 @@ Py_DECREF(v); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -1826,10 +1826,10 @@ TARGET_WITH_IMPL_NOARG(SLICE, _slice) TARGET_WITH_IMPL_NOARG(SLICE_1, _slice) - TARGET_WITH_IMPL_NOARG(SLICE_2, _slice) - TARGET_WITH_IMPL_NOARG(SLICE_3, _slice) - _slice: - { + TARGET_WITH_IMPL_NOARG(SLICE_2, _slice) + TARGET_WITH_IMPL_NOARG(SLICE_3, _slice) + _slice: + { if ((opcode-SLICE) & 2) w = POP(); else @@ -1844,17 +1844,17 @@ Py_XDECREF(v); Py_XDECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; - } + } TARGET_WITH_IMPL_NOARG(STORE_SLICE, _store_slice) TARGET_WITH_IMPL_NOARG(STORE_SLICE_1, _store_slice) - TARGET_WITH_IMPL_NOARG(STORE_SLICE_2, _store_slice) - TARGET_WITH_IMPL_NOARG(STORE_SLICE_3, _store_slice) - _store_slice: - { + TARGET_WITH_IMPL_NOARG(STORE_SLICE_2, _store_slice) + TARGET_WITH_IMPL_NOARG(STORE_SLICE_3, _store_slice) + _store_slice: + { if ((opcode-STORE_SLICE) & 2) w = POP(); else @@ -1870,17 +1870,17 @@ Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; - } + } TARGET_WITH_IMPL_NOARG(DELETE_SLICE, _delete_slice) TARGET_WITH_IMPL_NOARG(DELETE_SLICE_1, _delete_slice) - TARGET_WITH_IMPL_NOARG(DELETE_SLICE_2, _delete_slice) - TARGET_WITH_IMPL_NOARG(DELETE_SLICE_3, _delete_slice) - _delete_slice: - { + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_2, _delete_slice) + TARGET_WITH_IMPL_NOARG(DELETE_SLICE_3, _delete_slice) + _delete_slice: + { if ((opcode-DELETE_SLICE) & 2) w = POP(); else @@ -1895,9 +1895,9 @@ Py_DECREF(u); Py_XDECREF(v); Py_XDECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; - } + } TARGET_NOARG(STORE_SUBSCR) { @@ -1910,7 +1910,7 @@ Py_DECREF(u); Py_DECREF(v); Py_DECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -1923,7 +1923,7 @@ err = PyObject_DelItem(v, w); Py_DECREF(v); Py_DECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2006,7 +2006,7 @@ Py_DECREF(v); Py_XDECREF(stream); stream = NULL; - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2018,8 +2018,8 @@ TARGET_NOARG(PRINT_NEWLINE) { - if (stream == NULL || stream == Py_None) - { + if (stream == NULL || stream == Py_None) + { w = PySys_GetObject("stdout"); if (w == NULL) { PyErr_SetString(PyExc_RuntimeError, @@ -2046,7 +2046,7 @@ #endif TARGET(RAISE_VARARGS) - { + { u = v = w = NULL; switch (oparg) { case 3: @@ -2067,15 +2067,15 @@ break; } break; - } + } TARGET_NOARG(LOAD_LOCALS) { - if ((x = f->f_locals) != NULL) - { + if ((x = f->f_locals) != NULL) + { Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } PyErr_SetString(PyExc_SystemError, "no locals"); break; @@ -2120,7 +2120,7 @@ Py_DECREF(v); } } - DISPATCH(); + DISPATCH(); } PREDICTED(END_FINALLY); @@ -2175,7 +2175,7 @@ else err = PyObject_SetItem(x, w, v); Py_DECREF(v); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } t = PyObject_Repr(w); @@ -2222,7 +2222,7 @@ PUSH(w); } Py_DECREF(v); - DISPATCH(); + DISPATCH(); } else if (PyList_CheckExact(v) && PyList_GET_SIZE(v) == oparg) { PyObject **items = \ @@ -2253,7 +2253,7 @@ err = PyObject_SetAttr(v, w, u); /* v.w = u */ Py_DECREF(v); Py_DECREF(u); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2274,7 +2274,7 @@ v = POP(); err = PyDict_SetItem(f->f_globals, w, v); Py_DECREF(v); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2328,7 +2328,7 @@ Py_INCREF(x); } PUSH(x); - DISPATCH(); + DISPATCH(); } TARGET(LOAD_GLOBAL) @@ -2352,7 +2352,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } d = (PyDictObject *)(f->f_builtins); e = d->ma_lookup(d, w, hash); @@ -2364,7 +2364,7 @@ if (x != NULL) { Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } goto load_global_error; } @@ -2383,7 +2383,7 @@ } Py_INCREF(x); PUSH(x); - DISPATCH(); + DISPATCH(); } TARGET(DELETE_FAST) @@ -2391,7 +2391,7 @@ x = GETLOCAL(oparg); if (x != NULL) { SETLOCAL(oparg, NULL); - DISPATCH(); + DISPATCH(); } format_exc_check_arg( PyExc_UnboundLocalError, @@ -2406,7 +2406,7 @@ x = freevars[oparg]; Py_INCREF(x); PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2416,7 +2416,7 @@ w = PyCell_Get(x); if (w != NULL) { PUSH(w); - DISPATCH(); + DISPATCH(); } err = -1; /* Don't stomp existing exception */ @@ -2444,7 +2444,7 @@ x = freevars[oparg]; PyCell_Set(x, w); Py_DECREF(w); - DISPATCH(); + DISPATCH(); } TARGET(BUILD_TUPLE) @@ -2456,7 +2456,7 @@ PyTuple_SET_ITEM(x, oparg, w); } PUSH(x); - DISPATCH(); + DISPATCH(); } break; } @@ -2470,7 +2470,7 @@ PyList_SET_ITEM(x, oparg, w); } PUSH(x); - DISPATCH(); + DISPATCH(); } break; } @@ -2490,7 +2490,7 @@ break; } PUSH(x); - DISPATCH(); + DISPATCH(); } break; } @@ -2499,7 +2499,7 @@ { x = _PyDict_NewPresized((Py_ssize_t)oparg); PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2513,7 +2513,7 @@ err = PyDict_SetItem(v, w, u); /* v[w] = u */ Py_DECREF(u); Py_DECREF(w); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2529,7 +2529,7 @@ Py_DECREF(w); if (err == 0) { PREDICT(JUMP_ABSOLUTE); - DISPATCH(); + DISPATCH(); } break; } @@ -2541,7 +2541,7 @@ x = PyObject_GetAttr(v, w); Py_DECREF(v); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2579,7 +2579,7 @@ if (x == NULL) break; PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); - DISPATCH(); + DISPATCH(); } TARGET(IMPORT_NAME) @@ -2624,7 +2624,7 @@ READ_TIMESTAMP(intr1); Py_DECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -2642,7 +2642,7 @@ READ_TIMESTAMP(intr1); PyFrame_LocalsToFast(f, 0); Py_DECREF(v); - if (err == 0) DISPATCH(); + if (err == 0) DISPATCH(); break; } @@ -2654,14 +2654,14 @@ x = import_from(v, w); READ_TIMESTAMP(intr1); PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } TARGET(JUMP_FORWARD) { JUMPBY(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); @@ -2670,12 +2670,12 @@ w = POP(); if (w == Py_True) { Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_False) { Py_DECREF(w); JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); Py_DECREF(w); @@ -2685,7 +2685,7 @@ JUMPTO(oparg); else break; - DISPATCH(); + DISPATCH(); } PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); @@ -2694,12 +2694,12 @@ w = POP(); if (w == Py_False) { Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_True) { Py_DECREF(w); JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); Py_DECREF(w); @@ -2711,7 +2711,7 @@ ; else break; - DISPATCH(); + DISPATCH(); } TARGET(JUMP_IF_FALSE_OR_POP) @@ -2720,11 +2720,11 @@ if (w == Py_True) { STACKADJ(-1); Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_False) { JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); if (err > 0) { @@ -2736,7 +2736,7 @@ JUMPTO(oparg); else break; - DISPATCH(); + DISPATCH(); } TARGET(JUMP_IF_TRUE_OR_POP) @@ -2745,11 +2745,11 @@ if (w == Py_False) { STACKADJ(-1); Py_DECREF(w); - FAST_DISPATCH(); + FAST_DISPATCH(); } if (w == Py_True) { JUMPTO(oparg); - FAST_DISPATCH(); + FAST_DISPATCH(); } err = PyObject_IsTrue(w); if (err > 0) { @@ -2762,7 +2762,7 @@ } else break; - DISPATCH(); + DISPATCH(); } PREDICTED_WITH_ARG(JUMP_ABSOLUTE); @@ -2779,7 +2779,7 @@ */ goto fast_next_opcode; #else - DISPATCH(); + DISPATCH(); #endif } @@ -2792,7 +2792,7 @@ if (x != NULL) { SET_TOP(x); PREDICT(FOR_ITER); - DISPATCH(); + DISPATCH(); } STACKADJ(-1); break; @@ -2808,7 +2808,7 @@ PUSH(x); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); - DISPATCH(); + DISPATCH(); } if (PyErr_Occurred()) { if (!PyErr_ExceptionMatches( @@ -2820,7 +2820,7 @@ x = v = POP(); Py_DECREF(v); JUMPBY(oparg); - DISPATCH(); + DISPATCH(); } TARGET_NOARG(BREAK_LOOP) @@ -2842,9 +2842,9 @@ TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) - TARGET(SETUP_FINALLY) - _setup_finally: - { + TARGET(SETUP_FINALLY) + _setup_finally: + { /* NOTE: If you add any new block-setup opcodes that are not try/except/finally handlers, you may need to update the PyGen_NeedsFinalizing() function. @@ -2852,8 +2852,8 @@ PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL()); - DISPATCH(); - } + DISPATCH(); + } @@ -2884,8 +2884,8 @@ STACK_LEVEL()); PUSH(x); - DISPATCH(); - } + DISPATCH(); + } } TARGET_NOARG(WITH_CLEANUP) @@ -2988,14 +2988,14 @@ #endif stack_pointer = sp; PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw) TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw) - TARGET(CALL_FUNCTION_VAR_KW) - _call_function_var_kw: + TARGET(CALL_FUNCTION_VAR_KW) + _call_function_var_kw: { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; @@ -3033,7 +3033,7 @@ Py_DECREF(w); } PUSH(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } @@ -3110,7 +3110,7 @@ Py_DECREF(v); Py_XDECREF(w); SET_TOP(x); - if (x != NULL) DISPATCH(); + if (x != NULL) DISPATCH(); break; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 02:16:19 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 24 Aug 2015 00:16:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyODEy?= =?utf-8?q?=3A_Fix_unittest_discovery_examples=2E?= Message-ID: <20150824001618.29049.68909@psf.io> https://hg.python.org/cpython/rev/e285606efb82 changeset: 97468:e285606efb82 branch: 3.4 parent: 97445:586195685aaf user: Robert Collins date: Mon Aug 24 12:14:28 2015 +1200 summary: Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. files: Doc/library/unittest.rst | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -271,8 +271,8 @@ as positional arguments in that order. The following two command lines are equivalent:: - python -m unittest discover -s project_directory -p '*_test.py' - python -m unittest discover project_directory '*_test.py' + python -m unittest discover -s project_directory -p "*_test.py" + python -m unittest discover project_directory "*_test.py" As well as being a path it is possible to pass a package name, for example ``myproject.subpackage.test``, as the start directory. The package name you diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -894,6 +894,7 @@ Madison May Lucas Maystre Arnaud Mazin +Pam McA'Nulty Matt McClure Rebecca McCreary Kirk McDonald diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -449,6 +449,9 @@ Documentation ------------- +- Issue #22812: Fix unittest discovery examples. + Patch from Pam McA'Nulty. + - Issue #24129: Clarify the reference documentation for name resolution. This includes removing the assumption that readers will be familiar with the name resolution scheme Python used prior to the introduction of lexical -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 02:16:19 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 24 Aug 2015 00:16:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2322812=3A_Fix_unittest_discovery_examples=2E?= Message-ID: <20150824001619.29350.90539@psf.io> https://hg.python.org/cpython/rev/875a851b9d5a changeset: 97469:875a851b9d5a branch: 3.5 parent: 97460:738de9a9a3ea parent: 97468:e285606efb82 user: Robert Collins date: Mon Aug 24 12:15:05 2015 +1200 summary: Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. files: Doc/library/unittest.rst | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -278,8 +278,8 @@ as positional arguments in that order. The following two command lines are equivalent:: - python -m unittest discover -s project_directory -p '*_test.py' - python -m unittest discover project_directory '*_test.py' + python -m unittest discover -s project_directory -p "*_test.py" + python -m unittest discover project_directory "*_test.py" As well as being a path it is possible to pass a package name, for example ``myproject.subpackage.test``, as the start directory. The package name you diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -920,6 +920,7 @@ Madison May Lucas Maystre Arnaud Mazin +Pam McA'Nulty Matt McClure Jack McCracken Rebecca McCreary diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,9 @@ Documentation ------------- +- Issue #22812: Fix unittest discovery examples. + Patch from Pam McA'Nulty. + What's New in Python 3.5.0 release candidate 2? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 02:16:19 2015 From: python-checkins at python.org (robert.collins) Date: Mon, 24 Aug 2015 00:16:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322812=3A_Fix_unittest_discovery_examples=2E?= Message-ID: <20150824001619.29063.96050@psf.io> https://hg.python.org/cpython/rev/d9ec88a1e5d6 changeset: 97470:d9ec88a1e5d6 parent: 97465:d90a65014c42 parent: 97469:875a851b9d5a user: Robert Collins date: Mon Aug 24 12:15:49 2015 +1200 summary: Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. files: Doc/library/unittest.rst | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -278,8 +278,8 @@ as positional arguments in that order. The following two command lines are equivalent:: - python -m unittest discover -s project_directory -p '*_test.py' - python -m unittest discover project_directory '*_test.py' + python -m unittest discover -s project_directory -p "*_test.py" + python -m unittest discover project_directory "*_test.py" As well as being a path it is possible to pass a package name, for example ``myproject.subpackage.test``, as the start directory. The package name you diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -920,6 +920,7 @@ Madison May Lucas Maystre Arnaud Mazin +Pam McA'Nulty Matt McClure Jack McCracken Rebecca McCreary diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -129,6 +129,9 @@ Documentation ------------- +- Issue #22812: Fix unittest discovery examples. + Patch from Pam McA'Nulty. + - Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. Patch from Zbigniew J?drzejewski-Szmek. -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Mon Aug 24 10:30:26 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Mon, 24 Aug 2015 08:30:26 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-24 Message-ID: Results for project python_default-nightly, build date 2015-08-24 09:02:21 commit: d9ec88a1e5d6c89b6d79327db7e9a4c261810842 revision date: 2015-08-24 03:15:49 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.19108% 1.12735% 7.47953% :-( pybench sec 0.13750% 0.12630% -2.34887% :-( regex_v8 sec 2.91262% 0.07972% -3.12669% :-| nbody sec 0.47443% -0.10689% -1.28215% :-| json_dump_v2 sec 0.20342% 0.23673% -0.49082% :-| normal_startup sec 0.91327% -0.10683% 0.09626% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Mon Aug 24 14:46:04 2015 From: python-checkins at python.org (eric.smith) Date: Mon, 24 Aug 2015 12:46:04 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Typos=2E?= Message-ID: <20150824124604.12115.87739@psf.io> https://hg.python.org/peps/rev/12fdcb0b3548 changeset: 5983:12fdcb0b3548 user: Eric V. Smith date: Mon Aug 24 08:00:49 2015 -0400 summary: Typos. files: pep-0498.txt | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -309,7 +309,7 @@ SyntaxError: invalid syntax But note that this works, since the newline is removed from the -string, and the spaces in from of the '1' are allowed in an +string, and the spaces in front of the '1' are allowed in an expression:: >>> f'{x+\ @@ -325,7 +325,7 @@ >>> width = 10 >>> precision = 4 >>> value = decimal.Decimal('12.34567') - >>> f'result: {value:{width}.{prevision}}' + >>> f'result: {value:{width}.{precision}}' 'result: 12.35' Once expressions in a format specifier are evaluated (if necessary), @@ -467,7 +467,7 @@ While $identifier is no doubt more familiar to shell scripters and users of some other languages, in Python str.format() is heavily used. A quick search of Python's standard library shows only a handful -of uses of string.Template, but over 1000 uses of str.format(). +of uses of string.Template, but hundreds of uses of str.format(). Another proposed alternative was to have the substituted text between \{ and } or between \{ and \}. While this syntax would probably be @@ -483,7 +483,7 @@ only single identifiers, or a limited subset of Python expressions (such as the subset supported by str.format()). This PEP supports full Python expressions inside the braces. Without full expressions, some -desirable usage would be forbidden:: +desirable usage would be cumbersome. For example:: >>> f'Column={col_idx+1}' >>> f'number of items: {len(items)}' @@ -618,8 +618,8 @@ >>> f'{(lambda x: x*2)(3)}' '6' -Future extensions: -================== +Future extensions +================= By using another leading character (say, 'i'), we could extend this proposal to cover internationalization and localization. The idea is -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 24 15:23:43 2015 From: python-checkins at python.org (eric.smith) Date: Mon, 24 Aug 2015 13:23:43 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_More_typos=2E?= Message-ID: <20150824132342.67747.1049@psf.io> https://hg.python.org/peps/rev/03c42fea80fe changeset: 5984:03c42fea80fe user: Eric V. Smith date: Mon Aug 24 09:20:50 2015 -0400 summary: More typos. files: pep-0498.txt | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -80,7 +80,7 @@ str.format() was added to address some of these problems with %-formatting. In particular, it uses normal function call syntax (and -therefor supports mutliple parameters) and it is extensible through +therefor supports multiple parameters) and it is extensible through the __format__() method on the object being converted to a string. See PEP-3101 for a detailed rationale. This PEP reuses much of the str.format() syntax and machinery, in order to provide continuity with @@ -248,7 +248,6 @@ But:: >>> 'name={name:10}'.interpolate({'name:10': name}) - 'name=Guido ' Traceback (most recent call last): File "", line 1, in KeyError: 'name' -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 24 18:51:32 2015 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Aug 2015 16:51:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzI0OTI2OiBGaXgg?= =?utf-8?q?typo_in_example=2E?= Message-ID: <20150824165131.29354.67733@psf.io> https://hg.python.org/cpython/rev/ff53dbcdc85f changeset: 97471:ff53dbcdc85f branch: 2.7 parent: 97467:61b77bdfbc54 user: R David Murray date: Mon Aug 24 12:50:50 2015 -0400 summary: #24926: Fix typo in example. files: Doc/library/htmlparser.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/htmlparser.rst b/Doc/library/htmlparser.rst --- a/Doc/library/htmlparser.rst +++ b/Doc/library/htmlparser.rst @@ -201,7 +201,7 @@ The content of Internet Explorer conditional comments (condcoms) will also be sent to this method, so, for ````, - this method will receive ``'[if IE 9]>IE-specific contentIE9-specific content https://hg.python.org/cpython/rev/6eb5e59886e1 changeset: 97472:6eb5e59886e1 branch: 3.4 parent: 97468:e285606efb82 user: R David Murray date: Mon Aug 24 12:55:03 2015 -0400 summary: #24926: Fix typo in example. files: Doc/library/html.parser.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -213,7 +213,7 @@ The content of Internet Explorer conditional comments (condcoms) will also be sent to this method, so, for ````, - this method will receive ``'[if IE 9]>IE-specific contentIE9-specific content https://hg.python.org/cpython/rev/ccde4da4d0de changeset: 97474:ccde4da4d0de parent: 97470:d9ec88a1e5d6 parent: 97473:ae9a9f201870 user: R David Murray date: Mon Aug 24 12:56:24 2015 -0400 summary: Merge: #24926: Fix typo in example. files: Doc/library/html.parser.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -185,7 +185,7 @@ The content of Internet Explorer conditional comments (condcoms) will also be sent to this method, so, for ````, - this method will receive ``'[if IE 9]>IE-specific contentIE9-specific content https://hg.python.org/cpython/rev/ae9a9f201870 changeset: 97473:ae9a9f201870 branch: 3.5 parent: 97469:875a851b9d5a parent: 97472:6eb5e59886e1 user: R David Murray date: Mon Aug 24 12:55:47 2015 -0400 summary: Merge: #24926: Fix typo in example. files: Doc/library/html.parser.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -185,7 +185,7 @@ The content of Internet Explorer conditional comments (condcoms) will also be sent to this method, so, for ````, - this method will receive ``'[if IE 9]>IE-specific contentIE9-specific content https://hg.python.org/peps/rev/ec11060d2f52 changeset: 5985:ec11060d2f52 user: Eric V. Smith date: Mon Aug 24 14:35:44 2015 -0400 summary: Remove str.interpolate. It's just an implementation detail. It can be exposed at a later date, if need be. files: pep-0498.txt | 115 +++----------------------------------- 1 files changed, 10 insertions(+), 105 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -41,9 +41,6 @@ >>> f'He said his name is {name!r}.' "He said his name is 'Fred'." -This PEP proposes a new method on the str type: -str.interpolate(). This method will be used to implement f-strings. - A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to support a subset of Python expressions, and did not support the type-specific string formatting (the __format__ method) which was @@ -164,11 +161,6 @@ globals() has access to far more information than needed to do the string interpolation. -If locals() and globals() were used, and if a future extension to this -PEP would add an internationalization layer before str.interpolate() -is called, a malicious translator could get access to additional -variables in the callers context. - Guido stated [#]_ that any solution to better string interpolation would not use locals() or globals(). @@ -216,58 +208,21 @@ brackets, or braces. The exception is that the '!=' operator is special cased. -str.interpolate() ------------------ - -str.interpolate(mapping) will be a new method on the str type. It -takes one argument: a mapping of field names to values. This method is -the same as str.format_map() [#]_, with one difference: it does not -interpret the field_name [#]_ in any way. The field_name is only used -to look up the replacement value in the supplied mapping object. Like -str.format() and str.format_map(), str.interpolate() does interpret -and apply the optional conversion and format_spec. Thus, a field_name -may not contain the characters ':' or '}', nor the strings '!s', '!r', -or '!a'. - -Examples:: - - >>> name = 'Guido' - >>> 'name={name}'.interpolate({'name': name}) - 'name=Guido' - - >>> '{date} was on a {date:%A}. It was {weather}.'.interpolate({'weather': 'sunny', 'date': datetime.date(1991, 10, 12)}) - '1991-10-12 was on a Saturday. It was sunny.' - -Like str.format_map(), only the field_name portion inside braces is -used to look up values in the mapping. The format_spec is not used as -part of this lookup. Thus:: - - >>> 'name={name:10}'.interpolate({'name': name}) - 'name=Guido ' - -But:: - - >>> 'name={name:10}'.interpolate({'name:10': name}) - Traceback (most recent call last): - File "", line 1, in - KeyError: 'name' - Code equivalence ---------------- -An f-string is evaluated at run time using a call to str.interpolate(). +The exact code used to implement f-strings is not specified. However, +it is guaranteed that any embedded value that is converted to a string +will use that value's __format__ method. This is the same mechanism +that str.format() uses to convert values to strings. For example, this code:: f'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi' -Will be be evaluated as:: +Might be be evaluated as:: - 'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi'.interpolate({'expr1': expr1, 'expr2': expr2, 'expr3': expr3}) - -Note that the string on which interpolate() is being called is -identical to the value of the f-string. - + ''.join(['abc', expr1.__format__(spec1), repr(expr2).__format__(spec2), 'def', str(spec3).__format__(''), 'ghi']) Expression evaluation --------------------- @@ -350,19 +305,7 @@ While the exact method of this run time concatenation is unspecified, the above code might evaluate to:: - ''.join(['ab', '{x}'.interpolate({'x': x}), '{c}', 'str<', 'str<{y:^4}>'.interpolate({'y': y}), 'de']) - -You are guaranteed, however, that there will be no compile time -combination of f-strings:: - - >>> x = 0 - >>> y = 1 - >>> f'{x}' f'{y}' - '01' - -Will result in 2 calls to str.interpolate(): once on the string '{x}', -and again on the string '{y}'. This guarantee is needed to facilitate -proposed future internationalization. + ''.join(['ab', x.__format__(''), '{c}', 'str<', y.__format__('^4'), 'de']) Error handling -------------- @@ -415,16 +358,7 @@ --------------------------------------------------------- For ease of readability, leading and trailing whitespace in -expressions is ignored. However, this does not affect the string or -keys passed to str.interpolate():: - - >>> x = 100 - >>> f'x = { x }' - 'x = 100' - -This would be evaluated as:: - - 'x = { x }'.interpolate({' x ': 100}) +expressions is ignored. Discussion ========== @@ -544,7 +478,7 @@ Triple quoted f-strings are allowed. These strings are parsed just as normal triple-quoted strings are. After parsing, the normal f-string -logic is applied, and str.interpolate() is called. +logic is applied, and __format__() on each value is called. Raw f-strings ------------- @@ -612,40 +546,11 @@ a plain lambda in an f-string expression, this is not seen as much of a limitation. -Lambdas may be used inside of parens:: +If you feel you must use lambdas, they may be used inside of parens:: >>> f'{(lambda x: x*2)(3)}' '6' -Future extensions -================= - -By using another leading character (say, 'i'), we could extend this -proposal to cover internationalization and localization. The idea is -that the string would be passed to some lookup function before -.interpolate() is called on it:: - - >>> name = 'Eric' - >>> i'Name: {name}' - -Could be translated as:: - - gettext.gettext('Name: {name}').interpolate({'name': name}) - -If gettext.gettext() returned '{name} es mi nombre', then the -resulting string would be 'Eric es mi nombre'. - -Any such internationalization work will be specified in an additional -PEP. In all likelyhood, such a PEP will need to propose one or more -additional optional parameters to str.interpolate() in order to handle -the string.Template case of "safe substitution", where the substituted -field_names are not found in the mapping argument. The choices might -be: use the field_name, use a default (possibly empty) string, or -raise an exception. - -There would obviously need to be some way to specify to the compiler -what lookup function would be called. - References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 24 21:48:18 2015 From: python-checkins at python.org (eric.smith) Date: Mon, 24 Aug 2015 19:48:18 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_some_examples_from_Pyth?= =?utf-8?q?on=27s_source=2E_Both_=27before=27_=28str=2Eformat=29_and?= Message-ID: <20150824194816.29061.14356@psf.io> https://hg.python.org/peps/rev/ada9f2770917 changeset: 5986:ada9f2770917 user: Eric V. Smith date: Mon Aug 24 15:49:18 2015 -0400 summary: Added some examples from Python's source. Both 'before' (str.format) and 'after' (f-strings). files: pep-0498.txt | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -551,6 +551,35 @@ >>> f'{(lambda x: x*2)(3)}' '6' +Examples from Python's source code +================================== + +Here are some examples from Python source code that currently use +str.format(), and how they would look with f-strings. This PEP does +not recommend wholesale converting to f-strings, these are just +examples of real-world usages of str.format() and how they'd look if +written from scratch using f-strings. + +Lib/asyncio/locks.py:: + + extra = '{},waiters:{}'.format(extra, len(self._waiters)) + extra = f'{extra},waiters:{len(self._waiters)}' + +Lib/configparser.py:: + + message.append(" [line {0:2d}]".format(lineno)) + message.append(f" [line {lineno:2d}]") + +Tools/clinic/clinic.py:: + + methoddef_name = "{}_METHODDEF".format(c_basename.upper()) + methoddef_name = f"{c_basename.upper()}_METHODDEF" + +python-config.py:: + + print("Usage: {0} [{1}]".format(sys.argv[0], '|'.join('--'+opt for opt in valid_opts)), file=sys.stderr) + print(f"Usage: {sys.argv[0]} [{'|'.join('--'+opt for opt in valid_opts)}]", file=sys.stderr) + References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 24 22:01:12 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 24 Aug 2015 20:01:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fix_for_one-le?= =?utf-8?q?tter_type_in_What=27s_New_In_Python_3=2E5=2E?= Message-ID: <20150824200112.21453.44897@psf.io> https://hg.python.org/cpython/rev/7382e5fe3a40 changeset: 97477:7382e5fe3a40 branch: 3.5 parent: 97475:5a9ac801f9b4 user: Larry Hastings date: Mon Aug 24 12:49:22 2015 -0700 summary: Fix for one-letter type in What's New In Python 3.5. files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -729,7 +729,7 @@ * New :func:`~os.path.commonpath` function that extracts common path prefix. Unlike the :func:`~os.path.commonprefix` function, it always returns a valid - patch. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) + path. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) pickle ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:01:12 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 24 Aug 2015 20:01:12 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge=2E?= Message-ID: <20150824200112.27321.28177@psf.io> https://hg.python.org/cpython/rev/6de089e4d5b3 changeset: 97478:6de089e4d5b3 branch: 3.5 parent: 97473:ae9a9f201870 parent: 97477:7382e5fe3a40 user: Larry Hastings date: Mon Aug 24 12:58:57 2015 -0700 summary: Merge. files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -729,7 +729,7 @@ * New :func:`~os.path.commonpath` function that extracts common path prefix. Unlike the :func:`~os.path.commonprefix` function, it always returns a valid - patch. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) + path. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) pickle ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:01:13 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 24 Aug 2015 20:01:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <20150824200112.29360.3750@psf.io> https://hg.python.org/cpython/rev/b597d234c09d changeset: 97479:b597d234c09d parent: 97474:ccde4da4d0de parent: 97476:283d7aa763ee user: Larry Hastings date: Mon Aug 24 12:59:38 2015 -0700 summary: Merge. files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -729,7 +729,7 @@ * New :func:`~os.path.commonpath` function that extracts common path prefix. Unlike the :func:`~os.path.commonprefix` function, it always returns a valid - patch. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) + path. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) pickle ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:01:13 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 24 Aug 2015 20:01:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Null_merge_from_3=2E5=2E?= Message-ID: <20150824200112.21453.30572@psf.io> https://hg.python.org/cpython/rev/53693a7e9776 changeset: 97480:53693a7e9776 parent: 97479:b597d234c09d parent: 97478:6de089e4d5b3 user: Larry Hastings date: Mon Aug 24 13:00:14 2015 -0700 summary: Null merge from 3.5. files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:01:20 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 24 Aug 2015 20:01:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_One-character_typo_fix=2E?= Message-ID: <20150824200112.19656.34399@psf.io> https://hg.python.org/cpython/rev/283d7aa763ee changeset: 97476:283d7aa763ee parent: 97351:8c55fb5a11d8 user: Larry Hastings date: Fri Aug 14 08:03:30 2015 -0700 summary: One-character typo fix. os.path.commonprefix always returns a valid *path*, not a valid *patch*. files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -729,7 +729,7 @@ * New :func:`~os.path.commonpath` function that extracts common path prefix. Unlike the :func:`~os.path.commonprefix` function, it always returns a valid - patch. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) + path. (Contributed by Rafik Draoui and Serhiy Storchaka in :issue:`10395`.) pickle ------ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:01:23 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 24 Aug 2015 20:01:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merged_in_brettcannon/cpython350/3=2E5_=28pull_request_=232=29?= Message-ID: <20150824200112.79927.13979@psf.io> https://hg.python.org/cpython/rev/5a9ac801f9b4 changeset: 97475:5a9ac801f9b4 branch: 3.5 parent: 97358:7cfe20a6395d parent: 97379:cf3a62a8d786 user: larry date: Tue Aug 11 18:59:15 2015 -0700 summary: Merged in brettcannon/cpython350/3.5 (pull request #2) Issue #24492: make sure that ``from ... import ...` raises an ImportError if __name__ is not defined on a package. files: Lib/test/test_import/__init__.py | 13 +++++++++++++ Misc/NEWS | 4 ++++ Python/ceval.c | 19 ++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -324,6 +324,19 @@ with self.assertRaisesRegex(ImportError, "^cannot import name 'bogus'"): from re import bogus + def test_from_import_AttributeError(self): + # Issue #24492: trying to import an attribute that raises an + # AttributeError should lead to an ImportError. + class AlwaysAttributeError: + def __getattr__(self, _): + raise AttributeError + + module_name = 'test_from_import_AttributeError' + self.addCleanup(unload, module_name) + sys.modules[module_name] = AlwaysAttributeError() + with self.assertRaises(ImportError): + from test_from_import_AttributeError import does_not_exist + @skip_if_dont_write_bytecode class FilePermissionTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,10 @@ Core and Builtins ----------------- +- Issue #24492: A "package" lacking a __name__ attribute when trying to perform + a ``from .. import ...`` statement will trigger an ImportError instead of an + AttributeError. + - Issue #24667: Resize odict in all cases that the underlying dict resizes. Library diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5085,19 +5085,24 @@ sys.modules. */ PyErr_Clear(); pkgname = _PyObject_GetAttrId(v, &PyId___name__); - if (pkgname == NULL) - return NULL; + if (pkgname == NULL) { + goto error; + } fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name); Py_DECREF(pkgname); - if (fullmodname == NULL) + if (fullmodname == NULL) { return NULL; + } x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname); - if (x == NULL) - PyErr_Format(PyExc_ImportError, "cannot import name %R", name); - else - Py_INCREF(x); Py_DECREF(fullmodname); + if (x == NULL) { + goto error; + } + Py_INCREF(x); return x; + error: + PyErr_Format(PyExc_ImportError, "cannot import name %R", name); + return NULL; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:13:56 2015 From: python-checkins at python.org (donald.stufft) Date: Mon, 24 Aug 2015 20:13:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Update_pip_to_?= =?utf-8?q?7=2E1=2E2_and_setuptools_to_18=2E2?= Message-ID: <20150824201356.12123.7780@psf.io> https://hg.python.org/cpython/rev/71b59d01eea5 changeset: 97481:71b59d01eea5 branch: 3.4 parent: 97472:6eb5e59886e1 user: Donald Stufft date: Mon Aug 24 16:13:48 2015 -0400 summary: Update pip to 7.1.2 and setuptools to 18.2 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "18.0.1" +_SETUPTOOLS_VERSION = "18.2" -_PIP_VERSION = "7.1.0" +_PIP_VERSION = "7.1.2" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl deleted file mode 100644 index 76fcad1c7efb6223b049967e84fda31f9fd68dfc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e490155f0ca7f4ddb64c93c39fb2efb8795cd08 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl deleted file mode 100644 index 67aaca50a921a164fac7d721bc2aa80735c5515e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4288d68e074466894d8a2342e113737df7b7649 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:14:36 2015 From: python-checkins at python.org (donald.stufft) Date: Mon, 24 Aug 2015 20:14:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_updated_to_pip_and_setuptools?= Message-ID: <20150824201435.21435.58175@psf.io> https://hg.python.org/cpython/rev/3802560d1612 changeset: 97482:3802560d1612 branch: 3.5 parent: 97478:6de089e4d5b3 parent: 97481:71b59d01eea5 user: Donald Stufft date: Mon Aug 24 16:14:20 2015 -0400 summary: Merge updated to pip and setuptools files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "18.0.1" +_SETUPTOOLS_VERSION = "18.2" -_PIP_VERSION = "7.1.0" +_PIP_VERSION = "7.1.2" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl deleted file mode 100644 index 76fcad1c7efb6223b049967e84fda31f9fd68dfc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e490155f0ca7f4ddb64c93c39fb2efb8795cd08 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl deleted file mode 100644 index 67aaca50a921a164fac7d721bc2aa80735c5515e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4288d68e074466894d8a2342e113737df7b7649 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:15:51 2015 From: python-checkins at python.org (donald.stufft) Date: Mon, 24 Aug 2015 20:15:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge_updated_pip_and_setuptools?= Message-ID: <20150824201549.79929.84205@psf.io> https://hg.python.org/cpython/rev/7cddf687de9c changeset: 97483:7cddf687de9c parent: 97480:53693a7e9776 parent: 97482:3802560d1612 user: Donald Stufft date: Mon Aug 24 16:15:36 2015 -0400 summary: merge updated pip and setuptools files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "18.0.1" +_SETUPTOOLS_VERSION = "18.2" -_PIP_VERSION = "7.1.0" +_PIP_VERSION = "7.1.2" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl deleted file mode 100644 index 76fcad1c7efb6223b049967e84fda31f9fd68dfc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e490155f0ca7f4ddb64c93c39fb2efb8795cd08 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl deleted file mode 100644 index 67aaca50a921a164fac7d721bc2aa80735c5515e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4288d68e074466894d8a2342e113737df7b7649 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 22:17:26 2015 From: python-checkins at python.org (donald.stufft) Date: Mon, 24 Aug 2015 20:17:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Update_pip_to_?= =?utf-8?q?7=2E1=2E2_and_setuptools_to_18=2E2?= Message-ID: <20150824201726.27295.57997@psf.io> https://hg.python.org/cpython/rev/da483bda6efc changeset: 97484:da483bda6efc branch: 2.7 parent: 97471:ff53dbcdc85f user: Donald Stufft date: Mon Aug 24 16:17:13 2015 -0400 summary: Update pip to 7.1.2 and setuptools to 18.2 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "18.0.1" +_SETUPTOOLS_VERSION = "18.2" -_PIP_VERSION = "7.1.0" +_PIP_VERSION = "7.1.2" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl deleted file mode 100644 index 76fcad1c7efb6223b049967e84fda31f9fd68dfc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e490155f0ca7f4ddb64c93c39fb2efb8795cd08 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl deleted file mode 100644 index 67aaca50a921a164fac7d721bc2aa80735c5515e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4288d68e074466894d8a2342e113737df7b7649 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 24 23:29:16 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 24 Aug 2015 21:29:16 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_a_preamble_t?= =?utf-8?q?o_a_first=3DNone_variant=2E?= Message-ID: <20150824212916.76189.39366@psf.io> https://hg.python.org/peps/rev/b5a16f2bf11e changeset: 5987:b5a16f2bf11e user: Alexander Belopolsky date: Mon Aug 24 17:29:10 2015 -0400 summary: PEP 495: Added a preamble to a first=None variant. files: pep-0495.txt | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -509,6 +509,12 @@ Backward Compatibility ...................... +It has been suggested that backward compatibility can be improved if +the default value of the ``first`` flag was ``None`` which would +signal that pre-PEP behavior is requested. Based on the analysis +below, we believe that the proposed changes with the ``first=True`` +default are sufficiently backward compatible. + This PEP provides only three ways for a program to discover that two otherwise identical datetime instances have different values of ``first``: (1) an explicit check of the ``first`` attribute; (2) if -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 25 06:19:07 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 25 Aug 2015 04:19:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2310708=3A_Add_a_link_to_devguide_in_Misc/Porting?= =?utf-8?q?=2E?= Message-ID: <20150825041907.76191.6549@psf.io> https://hg.python.org/cpython/rev/23f4d8bf4f83 changeset: 97486:23f4d8bf4f83 parent: 97483:7cddf687de9c parent: 97485:5b43ee3df43e user: Berker Peksag date: Tue Aug 25 07:18:42 2015 +0300 summary: Issue #10708: Add a link to devguide in Misc/Porting. files: Misc/Porting | 42 +--------------------------------------- 1 files changed, 1 insertions(+), 41 deletions(-) diff --git a/Misc/Porting b/Misc/Porting --- a/Misc/Porting +++ b/Misc/Porting @@ -1,41 +1,1 @@ -Q. I want to port Python to a new platform. How do I begin? - -A. I guess the two things to start with is to familiarize yourself -with are the development system for your target platform and the -generic build process for Python. Make sure you can compile and run a -simple hello-world program on your target platform. Make sure you can -compile and run the Python interpreter on a platform to which it has -already been ported (preferably Unix, but Mac or Windows will do, -too). - -I also would never start something like this without at least -medium-level understanding of your target platform (i.e. how it is -generally used, how to write platform specific apps etc.) and Python -(or else you'll never know how to test the results). - -The build process for Python, in particular the Makefiles in the -source distribution, will give you a hint on which files to compile -for Python. Not all source files are relevant -- some are platform -specific, others are only used in emergencies (e.g. getopt.c). The -Makefiles tell the story. - -You'll also need a pyconfig.h file tailored for your platform. You can -start with pyconfig.h.in, read the comments and turn on definitions that -apply to your platform. - -And you'll need a config.c file, which lists the built-in modules you -support. Start with Modules/config.c.in. - -Finally, you'll run into some things that aren't supported on your -target platform. Forget about the posix module for now -- simply take -it out of the config.c file. - -Bang on it until you get a >>> prompt. (You may have to disable the -importing of "site.py" by passing the -S option.) - -Then bang on it until it executes very simple Python statements. - -Now bang on it some more. At some point you'll want to use the os -module; this is the time to start thinking about what to do with the -posix module. It's okay to simply #ifdef out those functions that -cause problems; the remaining ones will be quite useful. +This document is moved to https://docs.python.org/devguide/faq.html#how-do-i-port-python-to-a-new-platform -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 06:19:07 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 25 Aug 2015 04:19:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzEwNzA4?= =?utf-8?q?=3A_Add_a_link_to_devguide_in_Misc/Porting=2E?= Message-ID: <20150825041907.21451.24296@psf.io> https://hg.python.org/cpython/rev/5b43ee3df43e changeset: 97485:5b43ee3df43e branch: 3.5 parent: 97482:3802560d1612 user: Berker Peksag date: Tue Aug 25 07:18:21 2015 +0300 summary: Issue #10708: Add a link to devguide in Misc/Porting. files: Misc/Porting | 42 +--------------------------------------- 1 files changed, 1 insertions(+), 41 deletions(-) diff --git a/Misc/Porting b/Misc/Porting --- a/Misc/Porting +++ b/Misc/Porting @@ -1,41 +1,1 @@ -Q. I want to port Python to a new platform. How do I begin? - -A. I guess the two things to start with is to familiarize yourself -with are the development system for your target platform and the -generic build process for Python. Make sure you can compile and run a -simple hello-world program on your target platform. Make sure you can -compile and run the Python interpreter on a platform to which it has -already been ported (preferably Unix, but Mac or Windows will do, -too). - -I also would never start something like this without at least -medium-level understanding of your target platform (i.e. how it is -generally used, how to write platform specific apps etc.) and Python -(or else you'll never know how to test the results). - -The build process for Python, in particular the Makefiles in the -source distribution, will give you a hint on which files to compile -for Python. Not all source files are relevant -- some are platform -specific, others are only used in emergencies (e.g. getopt.c). The -Makefiles tell the story. - -You'll also need a pyconfig.h file tailored for your platform. You can -start with pyconfig.h.in, read the comments and turn on definitions that -apply to your platform. - -And you'll need a config.c file, which lists the built-in modules you -support. Start with Modules/config.c.in. - -Finally, you'll run into some things that aren't supported on your -target platform. Forget about the posix module for now -- simply take -it out of the config.c file. - -Bang on it until you get a >>> prompt. (You may have to disable the -importing of "site.py" by passing the -S option.) - -Then bang on it until it executes very simple Python statements. - -Now bang on it some more. At some point you'll want to use the os -module; this is the time to start thinking about what to do with the -posix module. It's okay to simply #ifdef out those functions that -cause problems; the remaining ones will be quite useful. +This document is moved to https://docs.python.org/devguide/faq.html#how-do-i-port-python-to-a-new-platform -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 07:53:21 2015 From: python-checkins at python.org (martin.panter) Date: Tue, 25 Aug 2015 05:53:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0ODA4?= =?utf-8?q?=3A_Update_the_documentation_of_some_PyTypeObject_fields?= Message-ID: <20150825055321.79919.43129@psf.io> https://hg.python.org/cpython/rev/54a9c649281d changeset: 97487:54a9c649281d branch: 3.4 parent: 97481:71b59d01eea5 user: Martin Panter date: Tue Aug 25 05:06:39 2015 +0000 summary: Issue #24808: Update the documentation of some PyTypeObject fields Patch by Joseph Weston. files: Doc/c-api/typeobj.rst | 10 +++++----- Doc/extending/newtypes.rst | 6 +++--- Doc/includes/typestruct.h | 15 +++++++-------- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -94,7 +94,7 @@ This field is not inherited by subtypes. -.. c:member:: char* PyTypeObject.tp_name +.. c:member:: const char* PyTypeObject.tp_name Pointer to a NUL-terminated string containing the name of the type. For types that are accessible as module globals, the string should be the full module @@ -367,7 +367,7 @@ inherited individually. -.. c:member:: long PyTypeObject.tp_flags +.. c:member:: unsigned long PyTypeObject.tp_flags This field is a bit mask of various flags. Some flags indicate variant semantics for certain situations; others are used to indicate that certain @@ -467,7 +467,7 @@ .. versionadded:: 3.4 -.. c:member:: char* PyTypeObject.tp_doc +.. c:member:: const char* PyTypeObject.tp_doc An optional pointer to a NUL-terminated C string giving the docstring for this type object. This is exposed as the :attr:`__doc__` attribute on the type and @@ -614,7 +614,7 @@ +----------------+------------+ -.. c:member:: long PyTypeObject.tp_weaklistoffset +.. c:member:: Py_ssize_t PyTypeObject.tp_weaklistoffset If the instances of this type are weakly referenceable, this field is greater than zero and contains the offset in the instance structure of the weak @@ -781,7 +781,7 @@ .. XXX explain. -.. c:member:: long PyTypeObject.tp_dictoffset +.. c:member:: Py_ssize_t PyTypeObject.tp_dictoffset If the instances of this type have a dictionary containing instance variables, this field is non-zero and contains the offset in the instances of the type of diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -893,20 +893,20 @@ all the fields you need (even if they're initialized to ``0``) and then change the values to suit your new type. :: - char *tp_name; /* For printing */ + const char *tp_name; /* For printing */ The name of the type - as mentioned in the last section, this will appear in various places, almost entirely for diagnostic purposes. Try to choose something that will be helpful in such a situation! :: - int tp_basicsize, tp_itemsize; /* For allocation */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ These fields tell the runtime how much memory to allocate when new objects of this type are created. Python has some built-in support for variable length structures (think: strings, lists) which is where the :c:member:`~PyTypeObject.tp_itemsize` field comes in. This will be dealt with later. :: - char *tp_doc; + const char *tp_doc; Here you can put a string (or its address) that you want returned when the Python script references ``obj.__doc__`` to retrieve the doc string. diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -1,7 +1,7 @@ typedef struct _typeobject { PyObject_VAR_HEAD - char *tp_name; /* For printing, in format "." */ - int tp_basicsize, tp_itemsize; /* For allocation */ + const char *tp_name; /* For printing, in format "." */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ /* Methods to implement standard operations */ @@ -9,7 +9,7 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - void *tp_reserved; + void *tp_reserved; /* formerly known as tp_compare */ reprfunc tp_repr; /* Method suites for standard classes */ @@ -30,9 +30,9 @@ PyBufferProcs *tp_as_buffer; /* Flags to define presence of optional/expanded features */ - long tp_flags; + unsigned long tp_flags; - char *tp_doc; /* Documentation string */ + const char *tp_doc; /* Documentation string */ /* call function for all accessible objects */ traverseproc tp_traverse; @@ -44,7 +44,7 @@ richcmpfunc tp_richcompare; /* weak reference enabler */ - long tp_weaklistoffset; + Py_ssize_t tp_weaklistoffset; /* Iterators */ getiterfunc tp_iter; @@ -58,7 +58,7 @@ PyObject *tp_dict; descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; - long tp_dictoffset; + Py_ssize_t tp_dictoffset; initproc tp_init; allocfunc tp_alloc; newfunc tp_new; @@ -69,7 +69,6 @@ PyObject *tp_cache; PyObject *tp_subclasses; PyObject *tp_weaklist; - destructor tp_del; /* Type attribute cache version tag. Added in version 2.6 */ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1473,6 +1473,7 @@ Edward Welbourne Cliff Wells Rickard Westman +Joseph Weston Jeff Wheeler Christopher White David White diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -449,6 +449,9 @@ Documentation ------------- +- Issue #24808: Update the types of some PyTypeObject fields. Patch by + Joseph Weston. + - Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 07:53:21 2015 From: python-checkins at python.org (martin.panter) Date: Tue, 25 Aug 2015 05:53:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324808=3A_Merge_3=2E5_into_3=2E6?= Message-ID: <20150825055321.79921.90040@psf.io> https://hg.python.org/cpython/rev/2637e2593f01 changeset: 97489:2637e2593f01 parent: 97486:23f4d8bf4f83 parent: 97488:e81d692a00b1 user: Martin Panter date: Tue Aug 25 05:41:51 2015 +0000 summary: Issue #24808: Merge 3.5 into 3.6 files: Doc/c-api/typeobj.rst | 10 +++++----- Doc/extending/newtypes.rst | 6 +++--- Doc/includes/typestruct.h | 15 +++++++-------- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -94,7 +94,7 @@ This field is not inherited by subtypes. -.. c:member:: char* PyTypeObject.tp_name +.. c:member:: const char* PyTypeObject.tp_name Pointer to a NUL-terminated string containing the name of the type. For types that are accessible as module globals, the string should be the full module @@ -372,7 +372,7 @@ inherited individually. -.. c:member:: long PyTypeObject.tp_flags +.. c:member:: unsigned long PyTypeObject.tp_flags This field is a bit mask of various flags. Some flags indicate variant semantics for certain situations; others are used to indicate that certain @@ -472,7 +472,7 @@ .. versionadded:: 3.4 -.. c:member:: char* PyTypeObject.tp_doc +.. c:member:: const char* PyTypeObject.tp_doc An optional pointer to a NUL-terminated C string giving the docstring for this type object. This is exposed as the :attr:`__doc__` attribute on the type and @@ -619,7 +619,7 @@ +----------------+------------+ -.. c:member:: long PyTypeObject.tp_weaklistoffset +.. c:member:: Py_ssize_t PyTypeObject.tp_weaklistoffset If the instances of this type are weakly referenceable, this field is greater than zero and contains the offset in the instance structure of the weak @@ -786,7 +786,7 @@ .. XXX explain. -.. c:member:: long PyTypeObject.tp_dictoffset +.. c:member:: Py_ssize_t PyTypeObject.tp_dictoffset If the instances of this type have a dictionary containing instance variables, this field is non-zero and contains the offset in the instances of the type of diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -893,20 +893,20 @@ all the fields you need (even if they're initialized to ``0``) and then change the values to suit your new type. :: - char *tp_name; /* For printing */ + const char *tp_name; /* For printing */ The name of the type - as mentioned in the last section, this will appear in various places, almost entirely for diagnostic purposes. Try to choose something that will be helpful in such a situation! :: - int tp_basicsize, tp_itemsize; /* For allocation */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ These fields tell the runtime how much memory to allocate when new objects of this type are created. Python has some built-in support for variable length structures (think: strings, lists) which is where the :c:member:`~PyTypeObject.tp_itemsize` field comes in. This will be dealt with later. :: - char *tp_doc; + const char *tp_doc; Here you can put a string (or its address) that you want returned when the Python script references ``obj.__doc__`` to retrieve the doc string. diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -1,7 +1,7 @@ typedef struct _typeobject { PyObject_VAR_HEAD - char *tp_name; /* For printing, in format "." */ - int tp_basicsize, tp_itemsize; /* For allocation */ + const char *tp_name; /* For printing, in format "." */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ /* Methods to implement standard operations */ @@ -9,7 +9,7 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - PyAsyncMethods *tp_as_async; + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ reprfunc tp_repr; /* Method suites for standard classes */ @@ -30,9 +30,9 @@ PyBufferProcs *tp_as_buffer; /* Flags to define presence of optional/expanded features */ - long tp_flags; + unsigned long tp_flags; - char *tp_doc; /* Documentation string */ + const char *tp_doc; /* Documentation string */ /* call function for all accessible objects */ traverseproc tp_traverse; @@ -44,7 +44,7 @@ richcmpfunc tp_richcompare; /* weak reference enabler */ - long tp_weaklistoffset; + Py_ssize_t tp_weaklistoffset; /* Iterators */ getiterfunc tp_iter; @@ -58,7 +58,7 @@ PyObject *tp_dict; descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; - long tp_dictoffset; + Py_ssize_t tp_dictoffset; initproc tp_init; allocfunc tp_alloc; newfunc tp_new; @@ -69,7 +69,6 @@ PyObject *tp_cache; PyObject *tp_subclasses; PyObject *tp_weaklist; - destructor tp_del; /* Type attribute cache version tag. Added in version 2.6 */ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1520,6 +1520,7 @@ Edward Welbourne Cliff Wells Rickard Westman +Joseph Weston Jeff Wheeler Christopher White David White diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -129,6 +129,9 @@ Documentation ------------- +- Issue #24808: Update the types of some PyTypeObject fields. Patch by + Joseph Weston. + - Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 07:53:21 2015 From: python-checkins at python.org (martin.panter) Date: Tue, 25 Aug 2015 05:53:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324808=3A_Merge_3=2E4_into_3=2E5=3B_adjust_new_tp=5Fas?= =?utf-8?q?=5Fasync_field?= Message-ID: <20150825055321.29370.86558@psf.io> https://hg.python.org/cpython/rev/e81d692a00b1 changeset: 97488:e81d692a00b1 branch: 3.5 parent: 97485:5b43ee3df43e parent: 97487:54a9c649281d user: Martin Panter date: Tue Aug 25 05:25:21 2015 +0000 summary: Issue #24808: Merge 3.4 into 3.5; adjust new tp_as_async field files: Doc/c-api/typeobj.rst | 10 +++++----- Doc/extending/newtypes.rst | 6 +++--- Doc/includes/typestruct.h | 15 +++++++-------- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -94,7 +94,7 @@ This field is not inherited by subtypes. -.. c:member:: char* PyTypeObject.tp_name +.. c:member:: const char* PyTypeObject.tp_name Pointer to a NUL-terminated string containing the name of the type. For types that are accessible as module globals, the string should be the full module @@ -372,7 +372,7 @@ inherited individually. -.. c:member:: long PyTypeObject.tp_flags +.. c:member:: unsigned long PyTypeObject.tp_flags This field is a bit mask of various flags. Some flags indicate variant semantics for certain situations; others are used to indicate that certain @@ -472,7 +472,7 @@ .. versionadded:: 3.4 -.. c:member:: char* PyTypeObject.tp_doc +.. c:member:: const char* PyTypeObject.tp_doc An optional pointer to a NUL-terminated C string giving the docstring for this type object. This is exposed as the :attr:`__doc__` attribute on the type and @@ -619,7 +619,7 @@ +----------------+------------+ -.. c:member:: long PyTypeObject.tp_weaklistoffset +.. c:member:: Py_ssize_t PyTypeObject.tp_weaklistoffset If the instances of this type are weakly referenceable, this field is greater than zero and contains the offset in the instance structure of the weak @@ -786,7 +786,7 @@ .. XXX explain. -.. c:member:: long PyTypeObject.tp_dictoffset +.. c:member:: Py_ssize_t PyTypeObject.tp_dictoffset If the instances of this type have a dictionary containing instance variables, this field is non-zero and contains the offset in the instances of the type of diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -893,20 +893,20 @@ all the fields you need (even if they're initialized to ``0``) and then change the values to suit your new type. :: - char *tp_name; /* For printing */ + const char *tp_name; /* For printing */ The name of the type - as mentioned in the last section, this will appear in various places, almost entirely for diagnostic purposes. Try to choose something that will be helpful in such a situation! :: - int tp_basicsize, tp_itemsize; /* For allocation */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ These fields tell the runtime how much memory to allocate when new objects of this type are created. Python has some built-in support for variable length structures (think: strings, lists) which is where the :c:member:`~PyTypeObject.tp_itemsize` field comes in. This will be dealt with later. :: - char *tp_doc; + const char *tp_doc; Here you can put a string (or its address) that you want returned when the Python script references ``obj.__doc__`` to retrieve the doc string. diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -1,7 +1,7 @@ typedef struct _typeobject { PyObject_VAR_HEAD - char *tp_name; /* For printing, in format "." */ - int tp_basicsize, tp_itemsize; /* For allocation */ + const char *tp_name; /* For printing, in format "." */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ /* Methods to implement standard operations */ @@ -9,7 +9,7 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - PyAsyncMethods *tp_as_async; + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ reprfunc tp_repr; /* Method suites for standard classes */ @@ -30,9 +30,9 @@ PyBufferProcs *tp_as_buffer; /* Flags to define presence of optional/expanded features */ - long tp_flags; + unsigned long tp_flags; - char *tp_doc; /* Documentation string */ + const char *tp_doc; /* Documentation string */ /* call function for all accessible objects */ traverseproc tp_traverse; @@ -44,7 +44,7 @@ richcmpfunc tp_richcompare; /* weak reference enabler */ - long tp_weaklistoffset; + Py_ssize_t tp_weaklistoffset; /* Iterators */ getiterfunc tp_iter; @@ -58,7 +58,7 @@ PyObject *tp_dict; descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; - long tp_dictoffset; + Py_ssize_t tp_dictoffset; initproc tp_init; allocfunc tp_alloc; newfunc tp_new; @@ -69,7 +69,6 @@ PyObject *tp_cache; PyObject *tp_subclasses; PyObject *tp_weaklist; - destructor tp_del; /* Type attribute cache version tag. Added in version 2.6 */ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1519,6 +1519,7 @@ Edward Welbourne Cliff Wells Rickard Westman +Joseph Weston Jeff Wheeler Christopher White David White diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,9 @@ Documentation ------------- +- Issue #24808: Update the types of some PyTypeObject fields. Patch by + Joseph Weston. + - Issue #22812: Fix unittest discovery examples. Patch from Pam McA'Nulty. -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Tue Aug 25 15:29:42 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Tue, 25 Aug 2015 13:29:42 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-25 Message-ID: <078AA0FFE8C7034097F90205717F504611D757F8@IRSMSX102.ger.corp.intel.com> Results for project python_default-nightly, build date 2015-08-25 12:50:15 commit: 2637e2593f0100c7d3b6be76a83cd887518c5cb3 revision date: 2015-08-25 08:41:51 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.39498% -0.86262% 6.68142% :-( pybench sec 0.10925% 0.01488% -2.33364% :-( regex_v8 sec 2.84402% -0.07593% -3.20499% :-( nbody sec 0.31476% -2.32720% -3.63919% :-| json_dump_v2 sec 0.19086% -0.22378% -0.71569% :-| normal_startup sec 0.72331% -0.02609% -0.10319% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From python-checkins at python.org Tue Aug 25 22:37:32 2015 From: python-checkins at python.org (eric.smith) Date: Tue, 25 Aug 2015 20:37:32 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Note_a_few_implementation_det?= =?utf-8?q?ails_or_restrictions=2E?= Message-ID: <20150825203732.12129.62737@psf.io> https://hg.python.org/peps/rev/7158263e9634 changeset: 5988:7158263e9634 user: Eric V. Smith date: Tue Aug 25 16:38:29 2015 -0400 summary: Note a few implementation details or restrictions. files: pep-0498.txt | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -580,6 +580,29 @@ print("Usage: {0} [{1}]".format(sys.argv[0], '|'.join('--'+opt for opt in valid_opts)), file=sys.stderr) print(f"Usage: {sys.argv[0]} [{'|'.join('--'+opt for opt in valid_opts)}]", file=sys.stderr) +Implementation limitations +========================== + +Maximum of 255 expressions +-------------------------- + +Due to a CPython limit with the number of parameters to a function, an +f-string may not contain more that 255 expressions. This includes +expressions inside format specifiers. So this code would count as +having 2 expressions:: + + f'{x:.{width}}' + +Expressions with side effects +----------------------------- + +xxx + +Expressions used multiple times +------------------------------- + +xxx + References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Aug 25 23:25:08 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODQ3?= =?utf-8?q?=3A_Removes_vcruntime140=2Edll_dependency_from_Tcl/Tk=2E?= Message-ID: <20150825212508.22328.51572@psf.io> https://hg.python.org/cpython/rev/dc9bdddca59b changeset: 97492:dc9bdddca59b branch: 3.5 parent: 97475:5a9ac801f9b4 user: Steve Dower date: Wed Aug 19 08:39:12 2015 -0700 summary: Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. files: Misc/NEWS | 2 ++ PCbuild/get_externals.bat | 6 +++--- PCbuild/readme.txt | 2 +- PCbuild/tcl.vcxproj | 3 ++- PCbuild/tcltk.props | 4 ++-- PCbuild/tix.vcxproj | 6 ++---- PCbuild/tk.vcxproj | 4 ++-- Tools/msi/tcltk/tcltk.wixproj | 7 ------- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Library ------- +- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. + - Issue #24839: platform._syscmd_ver raises DeprecationWarning What's New in Python 3.5.0 release candidate 1? diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,9 +55,9 @@ bzip2-1.0.6 nasm-2.11.06 openssl-1.0.2d - tcl-core-8.6.4.1 - tk-8.6.4.1 - tix-8.4.3.4 + tcl-core-8.6.4.2 + tk-8.6.4.2 + tix-8.4.3.6 sqlite-3.8.11.0 xz-5.0.5 ) do ( diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -236,7 +236,7 @@ Homepage: http://www.sqlite.org/ _tkinter - Wraps version 8.6.1 of the Tk windowing system. + Wraps version 8.6.4 of the Tk windowing system. Homepage: http://www.tcl.tk/ diff --git a/PCbuild/tcl.vcxproj b/PCbuild/tcl.vcxproj --- a/PCbuild/tcl.vcxproj +++ b/PCbuild/tcl.vcxproj @@ -61,7 +61,8 @@ - symbols + ucrt + symbols,ucrt INSTALLDIR="$(OutDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -5,7 +5,7 @@ 8 6 4 - 1 + 2 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) @@ -13,7 +13,7 @@ 8 4 3 - 4 + 6 $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -56,11 +56,9 @@ - msvcrt - symbols,msvcrt BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 TCL_DBGX=g DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" - DEBUG=0 NODEBUG=1 + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=tg TK_DBGX=tg + DEBUG=0 NODEBUG=1 UCRT=1 TCL_DBGX=t TK_DBGX=t setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') diff --git a/PCbuild/tk.vcxproj b/PCbuild/tk.vcxproj --- a/PCbuild/tk.vcxproj +++ b/PCbuild/tk.vcxproj @@ -60,8 +60,8 @@ - msvcrt - symbols,msvcrt + ucrt + symbols,ucrt TCLDIR="$(tclDir.TrimEnd(`\`))" INSTALLDIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -27,13 +27,6 @@ DLLs\ tcltk_dlls
- - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ - DLLs\ - tcltk_dlls - $(tcltkDir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:08 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merged_in_stevedower/cpython350_=28pull_request_=236=29?= Message-ID: <20150825212508.29368.33138@psf.io> https://hg.python.org/cpython/rev/b77ceefc34ff changeset: 97494:b77ceefc34ff branch: 3.5 parent: 97491:c1523d5dee3c parent: 97493:72ce2c385b7a user: Larry Hastings date: Mon Aug 24 16:47:56 2015 -0700 summary: Merged in stevedower/cpython350 (pull request #6) Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. files: Misc/NEWS | 2 ++ PCbuild/get_externals.bat | 6 +++--- PCbuild/readme.txt | 2 +- PCbuild/tcl.vcxproj | 3 ++- PCbuild/tcltk.props | 4 ++-- PCbuild/tix.vcxproj | 6 ++---- PCbuild/tk.vcxproj | 4 ++-- Tools/msi/tcltk/tcltk.wixproj | 7 ------- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,8 @@ Library ------- +- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. + - Issue #24839: platform._syscmd_ver raises DeprecationWarning What's New in Python 3.5.0 release candidate 1? diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,9 +55,9 @@ bzip2-1.0.6 nasm-2.11.06 openssl-1.0.2d - tcl-core-8.6.4.1 - tk-8.6.4.1 - tix-8.4.3.4 + tcl-core-8.6.4.2 + tk-8.6.4.2 + tix-8.4.3.6 sqlite-3.8.11.0 xz-5.0.5 ) do ( diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -236,7 +236,7 @@ Homepage: http://www.sqlite.org/ _tkinter - Wraps version 8.6.1 of the Tk windowing system. + Wraps version 8.6.4 of the Tk windowing system. Homepage: http://www.tcl.tk/ diff --git a/PCbuild/tcl.vcxproj b/PCbuild/tcl.vcxproj --- a/PCbuild/tcl.vcxproj +++ b/PCbuild/tcl.vcxproj @@ -61,7 +61,8 @@ - symbols + ucrt + symbols,ucrt INSTALLDIR="$(OutDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -5,7 +5,7 @@ 8 6 4 - 1 + 2 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) @@ -13,7 +13,7 @@ 8 4 3 - 4 + 6 $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -56,11 +56,9 @@ - msvcrt - symbols,msvcrt BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 TCL_DBGX=g DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" - DEBUG=0 NODEBUG=1 + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=g TK_DBGX=g + DEBUG=0 NODEBUG=1 UCRT=1 setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') diff --git a/PCbuild/tk.vcxproj b/PCbuild/tk.vcxproj --- a/PCbuild/tk.vcxproj +++ b/PCbuild/tk.vcxproj @@ -60,8 +60,8 @@ - msvcrt - symbols,msvcrt + ucrt + symbols,ucrt TCLDIR="$(tclDir.TrimEnd(`\`))" INSTALLDIR="$(OutDir.TrimEnd(`\`))" DEBUGFLAGS="-wd4456 -wd4457 -wd4458 -wd4459 -wd4996" setlocal diff --git a/Tools/msi/tcltk/tcltk.wixproj b/Tools/msi/tcltk/tcltk.wixproj --- a/Tools/msi/tcltk/tcltk.wixproj +++ b/Tools/msi/tcltk/tcltk.wixproj @@ -27,13 +27,6 @@ DLLs\ tcltk_dlls - - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ - $(VCInstallDir)redist\$(Platform)\ - DLLs\ - tcltk_dlls - $(tcltkDir) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:09 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Rebuilt_Clinic?= =?utf-8?q?_generated_code=2E?= Message-ID: <20150825212509.12131.38851@psf.io> https://hg.python.org/cpython/rev/48df93730ecd changeset: 97498:48df93730ecd branch: 3.5 user: Larry Hastings date: Mon Aug 24 20:23:27 2015 -0700 summary: Rebuilt Clinic generated code. files: Python/clinic/import.c.h | 4 ++-- Python/import.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -322,7 +322,7 @@ "exec_builtin($module, mod, /)\n" "--\n" "\n" -"Initialize an extension module."); +"Initialize a built-in module."); #define _IMP_EXEC_BUILTIN_METHODDEF \ {"exec_builtin", (PyCFunction)_imp_exec_builtin, METH_O, _imp_exec_builtin__doc__}, @@ -352,4 +352,4 @@ #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=c38749cebcadbc3b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=32324a5e46cdfc4b input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2059,7 +2059,7 @@ static int _imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod) -/*[clinic end generated code: output=215e99876a27e284 input=77ebec0c2a10ecca]*/ +/*[clinic end generated code: output=215e99876a27e284 input=7beed5a2f12a60ca]*/ { return exec_builtin_or_dynamic(mod); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:11 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_missing_?= =?utf-8?q?IDLE_updates_to_Misc/NEWS_that_shipped_with_Python_3=2E5=2E0rc1?= =?utf-8?q?=2E?= Message-ID: <20150825212510.12127.53298@psf.io> https://hg.python.org/cpython/rev/67c92700fe26 changeset: 97505:67c92700fe26 branch: 3.5 user: Larry Hastings date: Tue Aug 25 13:51:14 2015 -0700 summary: Added missing IDLE updates to Misc/NEWS that shipped with Python 3.5.0rc1. files: Misc/NEWS | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -97,7 +97,21 @@ - Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. -- Issue #24867: Fix Task.get_stack() for 'async def' coroutines +IDLE +---- + +- Issue #23672: Allow Idle to edit and run files with astral chars in name. + Patch by Mohd Sanad Zaki Rizvi. + +- Issue 24745: Idle editor default font. Switch from Courier to + platform-sensitive TkFixedFont. This should not affect current customized + font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg + and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. + +- Issue #21192: Idle editor. When a file is run, put its name in the restart bar. + Do not print false prompts. Original patch by Adnan Umer. + +- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy. Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:11 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Move_misplaced?= =?utf-8?q?_Misc/NEWS_item_from_3=2E5=2E0rc1_to_3=2E5=2E0rc2=2E?= Message-ID: <20150825212510.21451.7048@psf.io> https://hg.python.org/cpython/rev/975451f118dc changeset: 97504:975451f118dc branch: 3.5 user: Larry Hastings date: Tue Aug 25 13:41:35 2015 -0700 summary: Move misplaced Misc/NEWS item from 3.5.0rc1 to 3.5.0rc2. files: Misc/NEWS | 36 ++++++++++++++++++------------------ 1 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,28 +28,28 @@ - Issue #21167: NAN operations are now handled correctly when python is compiled with ICC even if -fp-model strict is not specified. -Library -------- - -- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. - -- Issue #24839: platform._syscmd_ver raises DeprecationWarning - -- Issue #24867: Fix Task.get_stack() for 'async def' coroutines - - -What's New in Python 3.5.0 release candidate 1? -=============================================== - -Release date: 2015-08-09 - -Core and Builtins ------------------ - - Issue #24492: A "package" lacking a __name__ attribute when trying to perform a ``from .. import ...`` statement will trigger an ImportError instead of an AttributeError. +Library +------- + +- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. + +- Issue #24839: platform._syscmd_ver raises DeprecationWarning + +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + + +What's New in Python 3.5.0 release candidate 1? +=============================================== + +Release date: 2015-08-09 + +Core and Builtins +----------------- + - Issue #24667: Resize odict in all cases that the underlying dict resizes. Library -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:10 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Version_bump_f?= =?utf-8?q?or_Python_3=2E5=2E0rc2=2E?= Message-ID: <20150825212510.12137.17595@psf.io> https://hg.python.org/cpython/rev/cc15d736d860 changeset: 97500:cc15d736d860 branch: 3.5 tag: v3.5.0rc2 user: Larry Hastings date: Mon Aug 24 20:31:53 2015 -0700 summary: Version bump for Python 3.5.0rc2. files: Include/patchlevel.h | 4 ++-- Misc/NEWS | 2 +- README | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.5.0rc1+" +#define PY_VERSION "3.5.0rc2" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.5.0 release candidate 2? =============================================== -Release date: 2015-08-23 +Release date: 2015-08-25 Core and Builtins ----------------- diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.5.0 release candidate 1 +This is Python version 3.5.0 release candidate 2 ================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:10 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_tag_v3?= =?utf-8?q?=2E5=2E0rc2_for_changeset_cc15d736d860?= Message-ID: <20150825212510.12129.22412@psf.io> https://hg.python.org/cpython/rev/c8f6abfe291f changeset: 97501:c8f6abfe291f branch: 3.5 user: Larry Hastings date: Mon Aug 24 20:32:19 2015 -0700 summary: Added tag v3.5.0rc2 for changeset cc15d736d860 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -153,3 +153,4 @@ 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 +cc15d736d860303b9da90d43cd32db39bab048df v3.5.0rc2 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:11 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merge_from_Python_3=2E5=2E0_=28rc2=29_to_Python_3=2E5=2E1=2E?= Message-ID: <20150825212511.12125.72500@psf.io> https://hg.python.org/cpython/rev/0b49bcc09ed8 changeset: 97507:0b49bcc09ed8 branch: 3.5 parent: 97488:e81d692a00b1 parent: 97506:d64c1c22d1f7 user: Larry Hastings date: Tue Aug 25 14:13:55 2015 -0700 summary: Merge from Python 3.5.0 (rc2) to Python 3.5.1. files: .hgtags | 1 + Include/patchlevel.h | 4 +- Lib/importlib/_bootstrap.py | 2 +- Lib/pydoc_data/topics.py | 2 +- Misc/NEWS | 105 +++++++++++------------ Python/clinic/import.c.h | 29 ++++++- Python/import.c | 69 ++++++++++----- Python/importlib.h | 2 +- README | 2 +- 9 files changed, 131 insertions(+), 85 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -153,3 +153,4 @@ 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 +cc15d736d860303b9da90d43cd32db39bab048df v3.5.0rc2 diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.5.0rc1+" +#define PY_VERSION "3.5.0rc2+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -745,7 +745,7 @@ @classmethod def exec_module(self, module): """Exec a built-in module""" - _call_with_frames_removed(_imp.exec_dynamic, module) + _call_with_frames_removed(_imp.exec_builtin, module) @classmethod @_requires_builtin diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Aug 9 03:32:48 2015 +# Autogenerated by Sphinx on Mon Aug 24 20:29:23 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -6,47 +6,11 @@ What's New in Python 3.5.1 ========================== - Release date: TBA - Core and Builtins ----------------- - -Library -------- - -- Issue #20362: Honour TestCase.longMessage correctly in assertRegex. - Patch from Ilia Kurenkov. - -- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. - -- Issue #23572: Fixed functools.singledispatch on classes with falsy - metaclasses. Patch by Ethan Furman. - - -Documentation -------------- - -- Issue #24808: Update the types of some PyTypeObject fields. Patch by - Joseph Weston. - -- Issue #22812: Fix unittest discovery examples. - Patch from Pam McA'Nulty. - - -What's New in Python 3.5.0 release candidate 2? -=============================================== - -Release date: 2015-08-23 - -Core and Builtins ------------------ - -- Issue #21167: NAN operations are now handled correctly when python is - compiled with ICC even if -fp-model strict is not specified. - Library ------- @@ -59,11 +23,11 @@ - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. -- Issue #24847: Fixes tcltk installer layout of VC runtime DLL - -- Issue #24839: platform._syscmd_ver raises DeprecationWarning - -- Issue #24867: Fix Task.get_stack() for 'async def' coroutines +- Issue #20362: Honour TestCase.longMessage correctly in assertRegex. + Patch from Ilia Kurenkov. + +- Issue #23572: Fixed functools.singledispatch on classes with falsy + metaclasses. Patch by Ethan Furman. Documentation ------------- @@ -71,18 +35,49 @@ - Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. Patch from Zbigniew J?drzejewski-Szmek. -What's New in Python 3.5.0 release candidate 1? +- Issue #24808: Update the types of some PyTypeObject fields. Patch by + Joseph Weston. + +- Issue #22812: Fix unittest discovery examples. + Patch from Pam McA'Nulty. + + +What's New in Python 3.5.0 release candidate 2? =============================================== -Release date: 2015-08-09 +Release date: 2015-08-25 Core and Builtins ----------------- +- Issue #24769: Interpreter now starts properly when dynamic loading + is disabled. Patch by Petr Viktorin. + +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + - Issue #24492: A "package" lacking a __name__ attribute when trying to perform a ``from .. import ...`` statement will trigger an ImportError instead of an AttributeError. +Library +------- + +- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. + +- Issue #24839: platform._syscmd_ver raises DeprecationWarning + +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + + +What's New in Python 3.5.0 release candidate 1? +=============================================== + +Release date: 2015-08-09 + +Core and Builtins +----------------- + - Issue #24667: Resize odict in all cases that the underlying dict resizes. Library @@ -136,7 +131,7 @@ - Issue #23672: Allow Idle to edit and run files with astral chars in name. Patch by Mohd Sanad Zaki Rizvi. -- Issue 24745: Idle editor default font. Switch from Courier to +- Issue #24745: Idle editor default font. Switch from Courier to platform-sensitive TkFixedFont. This should not affect current customized font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. @@ -467,14 +462,14 @@ - Issue #14373: Added C implementation of functools.lru_cache(). Based on patches by Matt Joiner and Alexey Kachayev. -- Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir +- Issue #24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). - Issue #22189: collections.UserString now supports __getnewargs__(), __rmod__(), casefold(), format_map(), isprintable(), and maketrans(). Patch by Joe Jevnik. -- Issue 24244: Prevents termination when an invalid format string is +- Issue #24244: Prevents termination when an invalid format string is encountered on Windows in strftime. - Issue #23973: PEP 484: Add the typing module. @@ -612,26 +607,26 @@ - asyncio: async() function is deprecated in favour of ensure_future(). -- Issue 24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore +- Issue #24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore support new 'async with' syntax. Contributed by Yury Selivanov. -- Issue 24179: Support 'async for' for asyncio.StreamReader. +- Issue #24179: Support 'async for' for asyncio.StreamReader. Contributed by Yury Selivanov. -- Issue 24184: Add AsyncIterator and AsyncIterable ABCs to +- Issue #24184: Add AsyncIterator and AsyncIterable ABCs to collections.abc. Contributed by Yury Selivanov. -- Issue 22547: Implement informative __repr__ for inspect.BoundArguments. +- Issue #22547: Implement informative __repr__ for inspect.BoundArguments. Contributed by Yury Selivanov. -- Issue 24190: Implement inspect.BoundArgument.apply_defaults() method. +- Issue #24190: Implement inspect.BoundArgument.apply_defaults() method. Contributed by Yury Selivanov. -- Issue 20691: Add 'follow_wrapped' argument to +- Issue #20691: Add 'follow_wrapped' argument to inspect.Signature.from_callable() and inspect.signature(). Contributed by Yury Selivanov. -- Issue 24248: Deprecate inspect.Signature.from_function() and +- Issue #24248: Deprecate inspect.Signature.from_function() and inspect.Signature.from_builtin(). - Issue #23898: Fix inspect.classify_class_attrs() to support attributes @@ -733,7 +728,7 @@ - Issue #4254: Adds _curses.update_lines_cols() Patch by Arnon Yaari -- Issue 19933: Provide default argument for ndigits in round. Patch by +- Issue #19933: Provide default argument for ndigits in round. Patch by Vajrasky Kok. - Issue #23193: Add a numeric_owner parameter to @@ -2549,7 +2544,7 @@ - Issue #13936: Remove the ability of datetime.time instances to be considered false in boolean contexts. -- Issue 18931: selectors module now supports /dev/poll on Solaris. +- Issue #18931: selectors module now supports /dev/poll on Solaris. Patch by Giampaolo Rodola'. - Issue #19977: When the ``LC_TYPE`` locale is the POSIX locale (``C`` locale), diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -318,6 +318,33 @@ #endif /* defined(HAVE_DYNAMIC_LOADING) */ +PyDoc_STRVAR(_imp_exec_builtin__doc__, +"exec_builtin($module, mod, /)\n" +"--\n" +"\n" +"Initialize a built-in module."); + +#define _IMP_EXEC_BUILTIN_METHODDEF \ + {"exec_builtin", (PyCFunction)_imp_exec_builtin, METH_O, _imp_exec_builtin__doc__}, + +static int +_imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod); + +static PyObject * +_imp_exec_builtin(PyModuleDef *module, PyObject *mod) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = _imp_exec_builtin_impl(module, mod); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + #ifndef _IMP_CREATE_DYNAMIC_METHODDEF #define _IMP_CREATE_DYNAMIC_METHODDEF #endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */ @@ -325,4 +352,4 @@ #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=0f1059766dd58f88 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=32324a5e46cdfc4b input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1943,6 +1943,34 @@ return PyBool_FromLong((long) (p == NULL ? 0 : p->size)); } +/* Common implementation for _imp.exec_dynamic and _imp.exec_builtin */ +static int +exec_builtin_or_dynamic(PyObject *mod) { + PyModuleDef *def; + void *state; + + if (!PyModule_Check(mod)) { + return 0; + } + + def = PyModule_GetDef(mod); + if (def == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + state = PyModule_GetState(mod); + if (PyErr_Occurred()) { + return -1; + } + if (state) { + /* Already initialized; skip reload */ + return 0; + } + return PyModule_ExecDef(mod, def); +} + #ifdef HAVE_DYNAMIC_LOADING /*[clinic input] @@ -2014,35 +2042,29 @@ _imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod) /*[clinic end generated code: output=4b84f1301b22d4bd input=9fdbfcb250280d3a]*/ { - PyModuleDef *def; - void *state; - - if (!PyModule_Check(mod)) { - return 0; - } - - def = PyModule_GetDef(mod); - if (def == NULL) { - if (PyErr_Occurred()) { - return -1; - } - return 0; - } - state = PyModule_GetState(mod); - if (PyErr_Occurred()) { - return -1; - } - if (state) { - /* Already initialized; skip reload */ - return 0; - } - return PyModule_ExecDef(mod, def); + return exec_builtin_or_dynamic(mod); } #endif /* HAVE_DYNAMIC_LOADING */ /*[clinic input] +_imp.exec_builtin -> int + + mod: object + / + +Initialize a built-in module. +[clinic start generated code]*/ + +static int +_imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod) +/*[clinic end generated code: output=215e99876a27e284 input=7beed5a2f12a60ca]*/ +{ + return exec_builtin_or_dynamic(mod); +} + +/*[clinic input] dump buffer [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ @@ -2064,6 +2086,7 @@ _IMP_IS_FROZEN_METHODDEF _IMP_CREATE_DYNAMIC_METHODDEF _IMP_EXEC_DYNAMIC_METHODDEF + _IMP_EXEC_BUILTIN_METHODDEF _IMP__FIX_CO_FILENAME_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.5.0 release candidate 1 +This is Python version 3.5.0 release candidate 2 ================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Added_missing_?= =?utf-8?q?=23-marks_to_Misc/NEWS_lines=2E?= Message-ID: <20150825212511.76209.6361@psf.io> https://hg.python.org/cpython/rev/d64c1c22d1f7 changeset: 97506:d64c1c22d1f7 branch: 3.5 user: Larry Hastings date: Tue Aug 25 14:08:21 2015 -0700 summary: Added missing #-marks to Misc/NEWS lines. files: Misc/NEWS | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -103,7 +103,7 @@ - Issue #23672: Allow Idle to edit and run files with astral chars in name. Patch by Mohd Sanad Zaki Rizvi. -- Issue 24745: Idle editor default font. Switch from Courier to +- Issue #24745: Idle editor default font. Switch from Courier to platform-sensitive TkFixedFont. This should not affect current customized font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. @@ -434,14 +434,14 @@ - Issue #14373: Added C implementation of functools.lru_cache(). Based on patches by Matt Joiner and Alexey Kachayev. -- Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir +- Issue #24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). - Issue #22189: collections.UserString now supports __getnewargs__(), __rmod__(), casefold(), format_map(), isprintable(), and maketrans(). Patch by Joe Jevnik. -- Issue 24244: Prevents termination when an invalid format string is +- Issue #24244: Prevents termination when an invalid format string is encountered on Windows in strftime. - Issue #23973: PEP 484: Add the typing module. @@ -579,26 +579,26 @@ - asyncio: async() function is deprecated in favour of ensure_future(). -- Issue 24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore +- Issue #24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore support new 'async with' syntax. Contributed by Yury Selivanov. -- Issue 24179: Support 'async for' for asyncio.StreamReader. +- Issue #24179: Support 'async for' for asyncio.StreamReader. Contributed by Yury Selivanov. -- Issue 24184: Add AsyncIterator and AsyncIterable ABCs to +- Issue #24184: Add AsyncIterator and AsyncIterable ABCs to collections.abc. Contributed by Yury Selivanov. -- Issue 22547: Implement informative __repr__ for inspect.BoundArguments. +- Issue #22547: Implement informative __repr__ for inspect.BoundArguments. Contributed by Yury Selivanov. -- Issue 24190: Implement inspect.BoundArgument.apply_defaults() method. +- Issue #24190: Implement inspect.BoundArgument.apply_defaults() method. Contributed by Yury Selivanov. -- Issue 20691: Add 'follow_wrapped' argument to +- Issue #20691: Add 'follow_wrapped' argument to inspect.Signature.from_callable() and inspect.signature(). Contributed by Yury Selivanov. -- Issue 24248: Deprecate inspect.Signature.from_function() and +- Issue #24248: Deprecate inspect.Signature.from_function() and inspect.Signature.from_builtin(). - Issue #23898: Fix inspect.classify_class_attrs() to support attributes @@ -700,7 +700,7 @@ - Issue #4254: Adds _curses.update_lines_cols() Patch by Arnon Yaari -- Issue 19933: Provide default argument for ndigits in round. Patch by +- Issue #19933: Provide default argument for ndigits in round. Patch by Vajrasky Kok. - Issue #23193: Add a numeric_owner parameter to @@ -2516,7 +2516,7 @@ - Issue #13936: Remove the ability of datetime.time instances to be considered false in boolean contexts. -- Issue 18931: selectors module now supports /dev/poll on Solaris. +- Issue #18931: selectors module now supports /dev/poll on Solaris. Patch by Giampaolo Rodola'. - Issue #19977: When the ``LC_TYPE`` locale is the POSIX locale (``C`` locale), -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Post-release_u?= =?utf-8?q?pdates_for_Python_3=2E5=2E0rc2=2E?= Message-ID: <20150825212510.29057.62576@psf.io> https://hg.python.org/cpython/rev/7dc5594bb288 changeset: 97502:7dc5594bb288 branch: 3.5 user: Larry Hastings date: Tue Aug 25 13:30:58 2015 -0700 summary: Post-release updates for Python 3.5.0rc2. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.5.0rc2" +#define PY_VERSION "3.5.0rc2+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 release candidate 3? +=============================================== + +Release date: 2015-09-06 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 release candidate 2? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Add_missing_Mi?= =?utf-8?q?sc/NEWS_item_for_merged_pull_request_for_issue_=2324867=2E?= Message-ID: <20150825212510.19628.30667@psf.io> https://hg.python.org/cpython/rev/ad48d5a4ef40 changeset: 97503:ad48d5a4ef40 branch: 3.5 user: Larry Hastings date: Tue Aug 25 13:37:23 2015 -0700 summary: Add missing Misc/NEWS item for merged pull request for issue #24867. files: Misc/NEWS | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -35,6 +35,8 @@ - Issue #24839: platform._syscmd_ver raises DeprecationWarning +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + What's New in Python 3.5.0 release candidate 1? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E5_=28with_3=2E5=2E0rc2_changes=29_into_de?= =?utf-8?q?fault_=283=2E6=29=2E__Messy!?= Message-ID: <20150825212511.29071.14132@psf.io> https://hg.python.org/cpython/rev/f94fc2032bb1 changeset: 97508:f94fc2032bb1 parent: 97489:2637e2593f01 parent: 97507:0b49bcc09ed8 user: Larry Hastings date: Tue Aug 25 14:21:59 2015 -0700 summary: Merge from 3.5 (with 3.5.0rc2 changes) into default (3.6). Messy! files: .hgtags | 1 + Lib/importlib/_bootstrap.py | 2 +- Misc/NEWS | 204 ++++++++++++++++-------- Python/clinic/import.c.h | 29 +++- Python/import.c | 69 +++++-- Python/importlib.h | 2 +- README | 2 +- 7 files changed, 214 insertions(+), 95 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -153,3 +153,4 @@ 0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 +cc15d736d860303b9da90d43cd32db39bab048df v3.5.0rc2 diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -745,7 +745,7 @@ @classmethod def exec_module(self, module): """Exec a built-in module""" - _call_with_frames_removed(_imp.exec_dynamic, module) + _call_with_frames_removed(_imp.exec_builtin, module) @classmethod @_requires_builtin diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,48 +10,148 @@ Core and Builtins ----------------- -- Issue #21167: NAN operations are now handled correctly when python is - compiled with ICC even if -fp-model strict is not specified. - - Issue #9232: Modify Python's grammar to allow trailing commas in the argument list of a function declaration. For example, "def f(*, a = 3,): pass" is now legal. Patch from Mark Dickinson. -- Issue #24667: Resize odict in all cases that the underlying dict resizes. - Library ------- - Issue #24633: site-packages/README -> README.txt. -- Issue #20362: Honour TestCase.longMessage correctly in assertRegex. - Patch from Ilia Kurenkov. +- Issue #24879: help() and pydoc can now list named tuple fields in the + order they were defined rather than alphabetically. The ordering is + determined by the _fields attribute if present. + +- Issue #24874: Improve speed of itertools.cycle() and make its + pickle more compact. + +- Fix crash in itertools.cycle.__setstate__() when the first argument wasn't + a list. + +- Issue #20059: urllib.parse raises ValueError on all invalid ports. + Patch by Martin Panter. + +- Issue #24360: Improve __repr__ of argparse.Namespace() for invalid + identifiers. Patch by Matthias Bussonnier. + +- Issue #23426: run_setup was broken in distutils. + Patch from Alexander Belopolsky. + +- Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. + +- Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can + only be used with 'r'. Patch from Jeff Balogh and John O'Connor. + +- Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. + +- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. + Patch from Nicola Palumbo and Laurent De Buyst. + +- Issue #24426: Fast searching optimization in regular expressions now works + for patterns that starts with capturing groups. Fast searching optimization + now can't be disabled at compile time. + +- Issue #23661: unittest.mock side_effects can now be exceptions again. This + was a regression vs Python 3.4. Patch from Ignacio Rossi + +- Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo + functions. + +Documentation +------------- + +Tests +----- + + +What's New in Python 3.5.1 +========================== + +Release date: TBA + +Core and Builtins +----------------- + +Library +------- - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. -- Issue #24879: help() and pydoc can now list named tuple fields in the - order they were defined rather than alphabetically. The ordering is - determined by the _fields attribute if present. - - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. Patch from ?ukasz Langa. -- Issue #24874: Improve speed of itertools.cycle() and make its - pickle more compact. - -- Fix crash in itertools.cycle.__setstate__() when the first argument wasn't - a list. - -- Issue #20059: urllib.parse raises ValueError on all invalid ports. - Patch by Martin Panter. +- Issue #20362: Honour TestCase.longMessage correctly in assertRegex. + Patch from Ilia Kurenkov. + +- Issue #23572: Fixed functools.singledispatch on classes with falsy + metaclasses. Patch by Ethan Furman. + +Documentation +------------- + +- Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. + Patch from Zbigniew J?drzejewski-Szmek. + +- Issue #24808: Update the types of some PyTypeObject fields. Patch by + Joseph Weston. + +- Issue #22812: Fix unittest discovery examples. + Patch from Pam McA'Nulty. + + +What's New in Python 3.5.0 release candidate 2? +=============================================== + +Release date: 2015-08-25 + +Core and Builtins +----------------- + +- Issue #24769: Interpreter now starts properly when dynamic loading + is disabled. Patch by Petr Viktorin. + +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + +- Issue #24492: A "package" lacking a __name__ attribute when trying to perform + a ``from .. import ...`` statement will trigger an ImportError instead of an + AttributeError. + +Library +------- + +- Issue #24847: Removes vcruntime140.dll dependency from Tcl/Tk. + +- Issue #24839: platform._syscmd_ver raises DeprecationWarning + +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + + +What's New in Python 3.5.0 release candidate 1? +=============================================== + +Release date: 2015-08-09 + +Core and Builtins +----------------- + +- Issue #24667: Resize odict in all cases that the underlying dict resizes. + +Library +------- - Issue #24824: Signatures of codecs.encode() and codecs.decode() now are compatible with pydoc. +- Issue #24634: Importing uuid should not try to load libc on Windows + +- Issue #24798: _msvccompiler.py doesn't properly support manifests + - Issue #4395: Better testing and documentation of binary operators. Patch by Martin Panter. @@ -72,43 +172,20 @@ - Issue #23779: imaplib raises TypeError if authenticator tries to abort. Patch from Craig Holmquist. -- Issue #24360: Improve __repr__ of argparse.Namespace() for invalid - identifiers. Patch by Matthias Bussonnier. - - Issue #23319: Fix ctypes.BigEndianStructure, swap correctly bytes. Patch written by Matthieu Gautier. -- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - - Issue #23254: Document how to close the TCPServer listening socket. Patch from Martin Panter. -- Issue #23426: run_setup was broken in distutils. - Patch from Alexander Belopolsky. +- Issue #19450: Update Windows and OS X installer builds to use SQLite 3.8.11. - Issue #17527: Add PATCH to wsgiref.validator. Patch from Luca Sbardella. -- Issue #13938: 2to3 converts StringTypes to a tuple. Patch from Mark Hammond. - -- Issue #2091: open() accepted a 'U' mode string containing '+', but 'U' can - only be used with 'r'. Patch from Jeff Balogh and John O'Connor. - -- Issue #8585: improved tests for zipimporter2. Patch from Mark Lawrence. - -- Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. - Patch from Nicola Palumbo and Laurent De Buyst. - -- Issue #24426: Fast searching optimization in regular expressions now works - for patterns that starts with capturing groups. Fast searching optimization - now can't be disabled at compile time. - -- Issue #23661: unittest.mock side_effects can now be exceptions again. This - was a regression vs Python 3.4. Patch from Ignacio Rossi - -- Issue #13248: Remove deprecated inspect.getargspec and inspect.getmoduleinfo - functions. - -- Issue #24867: Fix Task.get_stack() for 'async def' coroutines +- Issue #23812: Fix asyncio.Queue.get() to avoid loosing items on cancellation. + Patch by Gustavo J. A. M. Carneiro. + +- Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. IDLE ---- @@ -116,7 +193,7 @@ - Issue #23672: Allow Idle to edit and run files with astral chars in name. Patch by Mohd Sanad Zaki Rizvi. -- Issue 24745: Idle editor default font. Switch from Courier to +- Issue #24745: Idle editor default font. Switch from Courier to platform-sensitive TkFixedFont. This should not affect current customized font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman. @@ -129,15 +206,6 @@ Documentation ------------- -- Issue #24808: Update the types of some PyTypeObject fields. Patch by - Joseph Weston. - -- Issue #22812: Fix unittest discovery examples. - Patch from Pam McA'Nulty. - -- Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. - Patch from Zbigniew J?drzejewski-Szmek. - - Issue #24129: Clarify the reference documentation for name resolution. This includes removing the assumption that readers will be familiar with the name resolution scheme Python used prior to the introduction of lexical @@ -455,14 +523,14 @@ - Issue #14373: Added C implementation of functools.lru_cache(). Based on patches by Matt Joiner and Alexey Kachayev. -- Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir +- Issue #24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). - Issue #22189: collections.UserString now supports __getnewargs__(), __rmod__(), casefold(), format_map(), isprintable(), and maketrans(). Patch by Joe Jevnik. -- Issue 24244: Prevents termination when an invalid format string is +- Issue #24244: Prevents termination when an invalid format string is encountered on Windows in strftime. - Issue #23973: PEP 484: Add the typing module. @@ -600,26 +668,26 @@ - asyncio: async() function is deprecated in favour of ensure_future(). -- Issue 24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore +- Issue #24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore support new 'async with' syntax. Contributed by Yury Selivanov. -- Issue 24179: Support 'async for' for asyncio.StreamReader. +- Issue #24179: Support 'async for' for asyncio.StreamReader. Contributed by Yury Selivanov. -- Issue 24184: Add AsyncIterator and AsyncIterable ABCs to +- Issue #24184: Add AsyncIterator and AsyncIterable ABCs to collections.abc. Contributed by Yury Selivanov. -- Issue 22547: Implement informative __repr__ for inspect.BoundArguments. +- Issue #22547: Implement informative __repr__ for inspect.BoundArguments. Contributed by Yury Selivanov. -- Issue 24190: Implement inspect.BoundArgument.apply_defaults() method. +- Issue #24190: Implement inspect.BoundArgument.apply_defaults() method. Contributed by Yury Selivanov. -- Issue 20691: Add 'follow_wrapped' argument to +- Issue #20691: Add 'follow_wrapped' argument to inspect.Signature.from_callable() and inspect.signature(). Contributed by Yury Selivanov. -- Issue 24248: Deprecate inspect.Signature.from_function() and +- Issue #24248: Deprecate inspect.Signature.from_function() and inspect.Signature.from_builtin(). - Issue #23898: Fix inspect.classify_class_attrs() to support attributes @@ -721,7 +789,7 @@ - Issue #4254: Adds _curses.update_lines_cols() Patch by Arnon Yaari -- Issue 19933: Provide default argument for ndigits in round. Patch by +- Issue #19933: Provide default argument for ndigits in round. Patch by Vajrasky Kok. - Issue #23193: Add a numeric_owner parameter to @@ -2537,7 +2605,7 @@ - Issue #13936: Remove the ability of datetime.time instances to be considered false in boolean contexts. -- Issue 18931: selectors module now supports /dev/poll on Solaris. +- Issue #18931: selectors module now supports /dev/poll on Solaris. Patch by Giampaolo Rodola'. - Issue #19977: When the ``LC_TYPE`` locale is the POSIX locale (``C`` locale), diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -318,6 +318,33 @@ #endif /* defined(HAVE_DYNAMIC_LOADING) */ +PyDoc_STRVAR(_imp_exec_builtin__doc__, +"exec_builtin($module, mod, /)\n" +"--\n" +"\n" +"Initialize a built-in module."); + +#define _IMP_EXEC_BUILTIN_METHODDEF \ + {"exec_builtin", (PyCFunction)_imp_exec_builtin, METH_O, _imp_exec_builtin__doc__}, + +static int +_imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod); + +static PyObject * +_imp_exec_builtin(PyModuleDef *module, PyObject *mod) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = _imp_exec_builtin_impl(module, mod); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + #ifndef _IMP_CREATE_DYNAMIC_METHODDEF #define _IMP_CREATE_DYNAMIC_METHODDEF #endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */ @@ -325,4 +352,4 @@ #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=0f1059766dd58f88 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=32324a5e46cdfc4b input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1943,6 +1943,34 @@ return PyBool_FromLong((long) (p == NULL ? 0 : p->size)); } +/* Common implementation for _imp.exec_dynamic and _imp.exec_builtin */ +static int +exec_builtin_or_dynamic(PyObject *mod) { + PyModuleDef *def; + void *state; + + if (!PyModule_Check(mod)) { + return 0; + } + + def = PyModule_GetDef(mod); + if (def == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + state = PyModule_GetState(mod); + if (PyErr_Occurred()) { + return -1; + } + if (state) { + /* Already initialized; skip reload */ + return 0; + } + return PyModule_ExecDef(mod, def); +} + #ifdef HAVE_DYNAMIC_LOADING /*[clinic input] @@ -2014,35 +2042,29 @@ _imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod) /*[clinic end generated code: output=4b84f1301b22d4bd input=9fdbfcb250280d3a]*/ { - PyModuleDef *def; - void *state; - - if (!PyModule_Check(mod)) { - return 0; - } - - def = PyModule_GetDef(mod); - if (def == NULL) { - if (PyErr_Occurred()) { - return -1; - } - return 0; - } - state = PyModule_GetState(mod); - if (PyErr_Occurred()) { - return -1; - } - if (state) { - /* Already initialized; skip reload */ - return 0; - } - return PyModule_ExecDef(mod, def); + return exec_builtin_or_dynamic(mod); } #endif /* HAVE_DYNAMIC_LOADING */ /*[clinic input] +_imp.exec_builtin -> int + + mod: object + / + +Initialize a built-in module. +[clinic start generated code]*/ + +static int +_imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod) +/*[clinic end generated code: output=215e99876a27e284 input=7beed5a2f12a60ca]*/ +{ + return exec_builtin_or_dynamic(mod); +} + +/*[clinic input] dump buffer [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ @@ -2064,6 +2086,7 @@ _IMP_IS_FROZEN_METHODDEF _IMP_CREATE_DYNAMIC_METHODDEF _IMP_EXEC_DYNAMIC_METHODDEF + _IMP_EXEC_BUILTIN_METHODDEF _IMP__FIX_CO_FILENAME_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] diff --git a/README b/README --- a/README +++ b/README @@ -166,7 +166,7 @@ Release Schedule ---------------- -See PEP 478 for release details: http://www.python.org/dev/peps/pep-0478/ +See PEP 494 for release details: http://www.python.org/dev/peps/pep-0494/ Copyright and License Information -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merged_in_1st1/cpython350_=28pull_request_=235=29?= Message-ID: <20150825212509.29045.63639@psf.io> https://hg.python.org/cpython/rev/9b28f41f1353 changeset: 97496:9b28f41f1353 branch: 3.5 parent: 97494:b77ceefc34ff parent: 97495:595614c08eeb user: Larry Hastings date: Mon Aug 24 16:53:45 2015 -0700 summary: Merged in 1st1/cpython350 (pull request #5) Issue #24867: Fix asyncio.Task.get_stack() for 'async def' coroutines files: Lib/asyncio/tasks.py | 6 ++- Lib/test/test_asyncio/test_pep492.py | 17 ++++++++ Lib/test/test_asyncio/test_tasks.py | 32 ++++++++++++++++ Misc/NEWS | 2 + 4 files changed, 56 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -128,7 +128,11 @@ returned for a suspended coroutine. """ frames = [] - f = self._coro.gi_frame + try: + # 'async def' coroutines + f = self._coro.cr_frame + except AttributeError: + f = self._coro.gi_frame if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -186,6 +186,23 @@ data = self.loop.run_until_complete(coro()) self.assertEqual(data, 'spam') + def test_task_print_stack(self): + T = None + + async def foo(): + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + async def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + await T + + self.loop.run_until_complete(runner()) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2,6 +2,7 @@ import contextlib import functools +import io import os import re import sys @@ -162,6 +163,37 @@ 'function is deprecated, use ensure_'): self.assertIs(f, asyncio.async(f)) + def test_get_stack(self): + T = None + + @asyncio.coroutine + def foo(): + yield from bar() + + @asyncio.coroutine + def bar(): + # test get_stack() + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + # test print_stack() + file = io.StringIO() + T.print_stack(limit=1, file=file) + file.seek(0) + tb = file.read() + self.assertRegex(tb, r'foo\(\) running') + + @asyncio.coroutine + def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + yield from T + + self.loop.run_until_complete(runner()) + def test_task_repr(self): self.loop.set_debug(False) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -79,6 +79,8 @@ - Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODY3?= =?utf-8?q?=3A_Fix_asyncio=2ETask=2Eget=5Fstack=28=29_for_=27async_def=27_?= =?utf-8?q?coroutines?= Message-ID: <20150825212508.67608.50666@psf.io> https://hg.python.org/cpython/rev/595614c08eeb changeset: 97495:595614c08eeb branch: 3.5 parent: 97475:5a9ac801f9b4 user: Yury Selivanov date: Mon Aug 17 14:46:51 2015 -0400 summary: Issue #24867: Fix asyncio.Task.get_stack() for 'async def' coroutines files: Lib/asyncio/tasks.py | 6 ++- Lib/test/test_asyncio/test_pep492.py | 17 ++++++++ Lib/test/test_asyncio/test_tasks.py | 32 ++++++++++++++++ Misc/NEWS | 2 + 4 files changed, 56 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -128,7 +128,11 @@ returned for a suspended coroutine. """ frames = [] - f = self._coro.gi_frame + try: + # 'async def' coroutines + f = self._coro.cr_frame + except AttributeError: + f = self._coro.gi_frame if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -186,6 +186,23 @@ data = self.loop.run_until_complete(coro()) self.assertEqual(data, 'spam') + def test_task_print_stack(self): + T = None + + async def foo(): + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + async def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + await T + + self.loop.run_until_complete(runner()) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2,6 +2,7 @@ import contextlib import functools +import io import os import re import sys @@ -162,6 +163,37 @@ 'function is deprecated, use ensure_'): self.assertIs(f, asyncio.async(f)) + def test_get_stack(self): + T = None + + @asyncio.coroutine + def foo(): + yield from bar() + + @asyncio.coroutine + def bar(): + # test get_stack() + f = T.get_stack(limit=1) + try: + self.assertEqual(f[0].f_code.co_name, 'foo') + finally: + f = None + + # test print_stack() + file = io.StringIO() + T.print_stack(limit=1, file=file) + file.seek(0) + tb = file.read() + self.assertRegex(tb, r'foo\(\) running') + + @asyncio.coroutine + def runner(): + nonlocal T + T = asyncio.ensure_future(foo(), loop=self.loop) + yield from T + + self.loop.run_until_complete(runner()) + def test_task_repr(self): self.loop.set_debug(False) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -74,6 +74,8 @@ - Issue #24791: Fix grammar regression for call syntax: 'g(*a or b)'. +- Issue #24867: Fix Task.get_stack() for 'async def' coroutines + Documentation ------------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Regenerated_py?= =?utf-8?q?doc_topics_for_Python_3=2E5=2E0rc2=2E?= Message-ID: <20150825212509.76181.19618@psf.io> https://hg.python.org/cpython/rev/25298e2d9025 changeset: 97499:25298e2d9025 branch: 3.5 user: Larry Hastings date: Mon Aug 24 20:30:34 2015 -0700 summary: Regenerated pydoc topics for Python 3.5.0rc2. files: Lib/pydoc_data/topics.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Aug 9 03:32:48 2015 +# Autogenerated by Sphinx on Mon Aug 24 20:29:23 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0NzY5?= =?utf-8?q?=3A_Interpreter_now_starts_properly_when_dynamic_loading?= Message-ID: <20150825212509.79939.98934@psf.io> https://hg.python.org/cpython/rev/931593401e3e changeset: 97497:931593401e3e branch: 3.5 user: Larry Hastings date: Mon Aug 24 19:53:56 2015 -0700 summary: Issue #24769: Interpreter now starts properly when dynamic loading is disabled. Patch by Petr Viktorin. files: Lib/importlib/_bootstrap.py | 2 +- Misc/NEWS | 4 + Python/clinic/import.c.h | 29 ++++++++++- Python/import.c | 69 ++++++++++++++++-------- Python/importlib.h | 2 +- 5 files changed, 80 insertions(+), 26 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -745,7 +745,7 @@ @classmethod def exec_module(self, module): """Exec a built-in module""" - _call_with_frames_removed(_imp.exec_dynamic, module) + _call_with_frames_removed(_imp.exec_builtin, module) @classmethod @_requires_builtin diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #24769: Interpreter now starts properly when dynamic loading + is disabled. Patch by Petr Viktorin. + - Issue #21167: NAN operations are now handled correctly when python is compiled with ICC even if -fp-model strict is not specified. @@ -20,6 +23,7 @@ - Issue #24839: platform._syscmd_ver raises DeprecationWarning + What's New in Python 3.5.0 release candidate 1? =============================================== diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -318,6 +318,33 @@ #endif /* defined(HAVE_DYNAMIC_LOADING) */ +PyDoc_STRVAR(_imp_exec_builtin__doc__, +"exec_builtin($module, mod, /)\n" +"--\n" +"\n" +"Initialize an extension module."); + +#define _IMP_EXEC_BUILTIN_METHODDEF \ + {"exec_builtin", (PyCFunction)_imp_exec_builtin, METH_O, _imp_exec_builtin__doc__}, + +static int +_imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod); + +static PyObject * +_imp_exec_builtin(PyModuleDef *module, PyObject *mod) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = _imp_exec_builtin_impl(module, mod); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + #ifndef _IMP_CREATE_DYNAMIC_METHODDEF #define _IMP_CREATE_DYNAMIC_METHODDEF #endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */ @@ -325,4 +352,4 @@ #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=0f1059766dd58f88 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c38749cebcadbc3b input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1943,6 +1943,34 @@ return PyBool_FromLong((long) (p == NULL ? 0 : p->size)); } +/* Common implementation for _imp.exec_dynamic and _imp.exec_builtin */ +static int +exec_builtin_or_dynamic(PyObject *mod) { + PyModuleDef *def; + void *state; + + if (!PyModule_Check(mod)) { + return 0; + } + + def = PyModule_GetDef(mod); + if (def == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + state = PyModule_GetState(mod); + if (PyErr_Occurred()) { + return -1; + } + if (state) { + /* Already initialized; skip reload */ + return 0; + } + return PyModule_ExecDef(mod, def); +} + #ifdef HAVE_DYNAMIC_LOADING /*[clinic input] @@ -2014,35 +2042,29 @@ _imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod) /*[clinic end generated code: output=4b84f1301b22d4bd input=9fdbfcb250280d3a]*/ { - PyModuleDef *def; - void *state; - - if (!PyModule_Check(mod)) { - return 0; - } - - def = PyModule_GetDef(mod); - if (def == NULL) { - if (PyErr_Occurred()) { - return -1; - } - return 0; - } - state = PyModule_GetState(mod); - if (PyErr_Occurred()) { - return -1; - } - if (state) { - /* Already initialized; skip reload */ - return 0; - } - return PyModule_ExecDef(mod, def); + return exec_builtin_or_dynamic(mod); } #endif /* HAVE_DYNAMIC_LOADING */ /*[clinic input] +_imp.exec_builtin -> int + + mod: object + / + +Initialize a built-in module. +[clinic start generated code]*/ + +static int +_imp_exec_builtin_impl(PyModuleDef *module, PyObject *mod) +/*[clinic end generated code: output=215e99876a27e284 input=77ebec0c2a10ecca]*/ +{ + return exec_builtin_or_dynamic(mod); +} + +/*[clinic input] dump buffer [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ @@ -2064,6 +2086,7 @@ _IMP_IS_FROZEN_METHODDEF _IMP_CREATE_DYNAMIC_METHODDEF _IMP_EXEC_DYNAMIC_METHODDEF + _IMP_EXEC_BUILTIN_METHODDEF _IMP__FIX_CO_FILENAME_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Merged_in_bitdancer/cpython350_=28pull_request_=234=29?= Message-ID: <20150825212508.19654.70337@psf.io> https://hg.python.org/cpython/rev/c1523d5dee3c changeset: 97491:c1523d5dee3c branch: 3.5 parent: 97477:7382e5fe3a40 parent: 97490:d93bb3d636cf user: Larry Hastings date: Mon Aug 24 16:44:44 2015 -0700 summary: Merged in bitdancer/cpython350 (pull request #4) #21167: Fix definition of NAN when ICC used without -fp-model strict. files: Include/pymath.h | 24 +++++++++++++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -150,7 +150,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -594,6 +594,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:20 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Fixes_file_tha?= =?utf-8?q?t_did_not_graft_correctly=2E?= Message-ID: <20150825212508.29047.71670@psf.io> https://hg.python.org/cpython/rev/72ce2c385b7a changeset: 97493:72ce2c385b7a branch: 3.5 user: Steve Dower date: Wed Aug 19 08:44:05 2015 -0700 summary: Fixes file that did not graft correctly. files: PCbuild/tix.vcxproj | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj --- a/PCbuild/tix.vcxproj +++ b/PCbuild/tix.vcxproj @@ -57,8 +57,8 @@ BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" - DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=tg TK_DBGX=tg - DEBUG=0 NODEBUG=1 UCRT=1 TCL_DBGX=t TK_DBGX=t + DEBUG=1 NODEBUG=0 UCRT=1 TCL_DBGX=g TK_DBGX=g + DEBUG=0 NODEBUG=1 UCRT=1 setlocal @(ExpectedOutputs->'if not exist "%(FullPath)" goto build',' ') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Aug 25 23:25:27 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 25 Aug 2015 21:25:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogIzIxMTY3OiBGaXgg?= =?utf-8?q?definition_of_NAN_when_ICC_used_without_-fp-model_strict=2E?= Message-ID: <20150825212507.79921.89907@psf.io> https://hg.python.org/cpython/rev/d93bb3d636cf changeset: 97490:d93bb3d636cf branch: 3.5 parent: 97475:5a9ac801f9b4 user: R David Murray date: Sat Aug 15 18:33:45 2015 -0400 summary: #21167: Fix definition of NAN when ICC used without -fp-model strict. Patch from Chris Hogan of Intel, reviewed by Mark Dickinson. files: Include/pymath.h | 24 +++++++++++++++++++++++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/Include/pymath.h b/Include/pymath.h --- a/Include/pymath.h +++ b/Include/pymath.h @@ -150,7 +150,29 @@ * doesn't support NaNs. */ #if !defined(Py_NAN) && !defined(Py_NO_NAN) -#define Py_NAN (Py_HUGE_VAL * 0.) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ #endif /* Py_OVERFLOWED(X) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -594,6 +594,7 @@ Chris Hoffman Stefan Hoffmeister Albert Hofkamp +Chris Hogan Tomas Hoger Jonathan Hogg Kamilla Holanda diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21167: NAN operations are now handled correctly when python is + compiled with ICC even if -fp-model strict is not specified. + Library ------- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 02:22:25 2015 From: python-checkins at python.org (larry.hastings) Date: Wed, 26 Aug 2015 00:22:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Misc/NEWS_need?= =?utf-8?q?s_a_Python_3=2E5=2E0rc3_section_in_3=2E5_and_trunk=2E?= Message-ID: <20150826002225.21455.74277@psf.io> https://hg.python.org/cpython/rev/91376b651e53 changeset: 97509:91376b651e53 branch: 3.5 parent: 97507:0b49bcc09ed8 user: Larry Hastings date: Tue Aug 25 17:21:22 2015 -0700 summary: Misc/NEWS needs a Python 3.5.0rc3 section in 3.5 and trunk. files: Misc/NEWS | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,18 @@ Patch from Pam McA'Nulty. +What's New in Python 3.5.0 release candidate 3? +=============================================== + +Release date: 2015-09-06 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 release candidate 2? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 02:22:39 2015 From: python-checkins at python.org (larry.hastings) Date: Wed, 26 Aug 2015 00:22:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <20150826002225.76191.27064@psf.io> https://hg.python.org/cpython/rev/2fca6a5137a5 changeset: 97510:2fca6a5137a5 parent: 97508:f94fc2032bb1 parent: 97509:91376b651e53 user: Larry Hastings date: Tue Aug 25 17:21:54 2015 -0700 summary: Merge. files: Misc/NEWS | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -104,6 +104,18 @@ Patch from Pam McA'Nulty. +What's New in Python 3.5.0 release candidate 3? +=============================================== + +Release date: 2015-09-06 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 release candidate 2? =============================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 02:40:51 2015 From: python-checkins at python.org (robert.collins) Date: Wed, 26 Aug 2015 00:40:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323552=3A_Timeit_n?= =?utf-8?q?ow_warns_when_there_is_substantial_=284x=29_variance?= Message-ID: <20150826004045.67747.233@psf.io> https://hg.python.org/cpython/rev/2e9cf58c891d changeset: 97511:2e9cf58c891d user: Robert Collins date: Wed Aug 26 12:40:28 2015 +1200 summary: Issue #23552: Timeit now warns when there is substantial (4x) variance between best and worst times. Patch from Serhiy Storchaka. files: Lib/timeit.py | 32 +++++++++++++++++++------------- Misc/NEWS | 3 +++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -317,20 +317,26 @@ print("%d loops," % number, end=' ') usec = best * 1e6 / number if time_unit is not None: - print("best of %d: %.*g %s per loop" % (repeat, precision, - usec/units[time_unit], time_unit)) + scale = units[time_unit] else: - if usec < 1000: - print("best of %d: %.*g usec per loop" % (repeat, precision, usec)) - else: - msec = usec / 1000 - if msec < 1000: - print("best of %d: %.*g msec per loop" % (repeat, - precision, msec)) - else: - sec = msec / 1000 - print("best of %d: %.*g sec per loop" % (repeat, - precision, sec)) + scales = [(scale, unit) for unit, scale in units.items()] + scales.sort(reverse=True) + for scale, time_unit in scales: + if usec >= scale: + break + print("best of %d: %.*g %s per loop" % (repeat, precision, + usec/scale, time_unit)) + best = min(r) + usec = best * 1e6 / number + worst = max(r) + if worst >= best * 4: + usec = worst * 1e6 / number + import warnings + warnings.warn_explicit( + "The test results are likely unreliable. The worst\n" + "time (%.*g %s) was more than four times slower than the best time." % + (precision, usec/scale, time_unit), + UserWarning, '', 0) return None if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,9 @@ Library ------- +- Issue #23552: Timeit now warns when there is substantial (4x) variance + between best and worst times. Patch from Serhiy Storchaka. + - Issue #24633: site-packages/README -> README.txt. - Issue #24879: help() and pydoc can now list named tuple fields in the -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Wed Aug 26 09:33:44 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Wed, 26 Aug 2015 07:33:44 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-26 Message-ID: <078AA0FFE8C7034097F90205717F504611D759C6@IRSMSX102.ger.corp.intel.com> Results for project python_default-nightly, build date 2015-08-26 09:02:49 commit: 2e9cf58c891d15e1aed704c3ca47aab05bd66cc8 revision date: 2015-08-26 03:40:28 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.26062% 0.78511% 7.41407% :-( pybench sec 0.21376% -0.02232% -2.35648% :-( regex_v8 sec 3.19488% -0.25510% -3.46827% :-) nbody sec 0.12129% 2.33023% -1.22416% :-| json_dump_v2 sec 0.32022% 0.08179% -0.63332% :-| normal_startup sec 0.85272% 0.17080% 0.10471% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Wed Aug 26 12:08:25 2015 From: python-checkins at python.org (eric.smith) Date: Wed, 26 Aug 2015 10:08:25 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_a_typo_found_by_Jochen_?= =?utf-8?q?Kupperschmidt=2E_Thanks!?= Message-ID: <20150826100819.67423.99402@psf.io> https://hg.python.org/peps/rev/44b5cc0053dd changeset: 5989:44b5cc0053dd user: Eric V. Smith date: Wed Aug 26 06:08:21 2015 -0400 summary: Fixed a typo found by Jochen Kupperschmidt. Thanks! files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -513,7 +513,7 @@ Both of these remain as options in the future, if such functionality is desired. -!s, !r, and !s are redundant +!s, !r, and !a are redundant ---------------------------- The !s, !r, and !a are not strictly required. Because arbitrary -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Aug 26 16:37:08 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 26 Aug 2015 14:37:08 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_=27which=27_?= =?utf-8?q?as_a_discussed_name_variant=2E?= Message-ID: <20150826143708.29350.76633@psf.io> https://hg.python.org/peps/rev/a89d5b843c3e changeset: 5990:a89d5b843c3e user: Alexander Belopolsky date: Wed Aug 26 10:37:02 2015 -0400 summary: PEP 495: Added 'which' as a discussed name variant. files: pep-0495.txt | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -486,7 +486,12 @@ ``.astimezone(timezone.utc)`` that that with ``later=False``. Yet again, this can be interpreted as a desirable indication that the original time is invalid. - + + **which** + The `original`_ placeholder name for the `localtime` function + branch index was `independently proposed`_ for the name of the + disambiguation attribute and received `some support`_. + **repeated** Did not receive any support on the mailing list. @@ -497,6 +502,9 @@ earlier if you don't want to endorse any of the alternatives above.) +.. _original: https://mail.python.org/pipermail/python-dev/2015-April/139099.html +.. _independently proposed: https://mail.python.org/pipermail/datetime-sig/2015-August/000479.html +.. _some support: https://mail.python.org/pipermail/datetime-sig/2015-August/000483.html Are two values enough? ---------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Aug 26 17:10:46 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 26 Aug 2015 15:10:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150826151016.76203.81860@psf.io> https://hg.python.org/cpython/rev/b66a8240925a changeset: 97513:b66a8240925a parent: 97511:2e9cf58c891d parent: 97512:ae8ec66adc7f user: Raymond Hettinger date: Wed Aug 26 08:09:50 2015 -0700 summary: merge files: Lib/test/test_deque.py | 5 +++++ Misc/NEWS | 3 +++ Modules/_collectionsmodule.c | 2 ++ 3 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -289,6 +289,11 @@ else: self.assertEqual(d.index(element, start, stop), target) + def test_insert_bug_24913(self): + d = deque('A' * 3) + with self.assertRaises(ValueError): + i = d.index("Hello world", 0, 4) + def test_insert(self): # Test to make sure insert behaves like lists elements = 'ABCDEFGHI' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -83,6 +83,9 @@ header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. +- Issue #24913: Fix overrun error in deque.index(). + Found by John Leitch and Bryce Darling. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -924,6 +924,8 @@ if (stop < 0) stop = 0; } + if (stop > Py_SIZE(deque)) + stop = Py_SIZE(deque); for (i=0 ; i= start) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 17:10:46 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 26 Aug 2015 15:10:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0OTEz?= =?utf-8?q?=3A_Fix_overrun_error_in_deque=2Eindex=28=29=2E?= Message-ID: <20150826151015.29043.92725@psf.io> https://hg.python.org/cpython/rev/ae8ec66adc7f changeset: 97512:ae8ec66adc7f branch: 3.5 parent: 97509:91376b651e53 user: Raymond Hettinger date: Wed Aug 26 08:08:38 2015 -0700 summary: Issue #24913: Fix overrun error in deque.index(). files: Lib/test/test_deque.py | 5 +++++ Misc/NEWS | 3 +++ Modules/_collectionsmodule.c | 2 ++ 3 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -289,6 +289,11 @@ else: self.assertEqual(d.index(element, start, stop), target) + def test_insert_bug_24913(self): + d = deque('A' * 3) + with self.assertRaises(ValueError): + i = d.index("Hello world", 0, 4) + def test_insert(self): # Test to make sure insert behaves like lists elements = 'ABCDEFGHI' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,9 @@ header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. +- Issue #24913: Fix overrun error in deque.index(). + Found by John Leitch and Bryce Darling. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -924,6 +924,8 @@ if (stop < 0) stop = 0; } + if (stop > Py_SIZE(deque)) + stop = Py_SIZE(deque); for (i=0 ; i= start) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 19:04:14 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 26 Aug 2015 17:04:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150826170413.21439.4726@psf.io> https://hg.python.org/cpython/rev/55fa2fba132c changeset: 97515:55fa2fba132c parent: 97513:b66a8240925a parent: 97514:9f7f6f7145f4 user: Yury Selivanov date: Wed Aug 26 13:04:06 2015 -0400 summary: Merge 3.5 files: Doc/includes/typestruct.h | 3 ++- Include/object.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -9,7 +9,8 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2) + or tp_reserved (Python 3) */ reprfunc tp_repr; /* Method suites for standard classes */ diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -351,7 +351,8 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2) + or tp_reserved (Python 3) */ reprfunc tp_repr; /* Method suites for standard classes */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 19:04:31 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 26 Aug 2015 17:04:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogZG9jczogQmV0dGVy?= =?utf-8?q?_comment_for_tp=5Fas=5Fasync_slot?= Message-ID: <20150826170413.19650.69774@psf.io> https://hg.python.org/cpython/rev/9f7f6f7145f4 changeset: 97514:9f7f6f7145f4 branch: 3.5 parent: 97512:ae8ec66adc7f user: Yury Selivanov date: Wed Aug 26 13:03:57 2015 -0400 summary: docs: Better comment for tp_as_async slot files: Doc/includes/typestruct.h | 3 ++- Include/object.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/includes/typestruct.h b/Doc/includes/typestruct.h --- a/Doc/includes/typestruct.h +++ b/Doc/includes/typestruct.h @@ -9,7 +9,8 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2) + or tp_reserved (Python 3) */ reprfunc tp_repr; /* Method suites for standard classes */ diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -351,7 +351,8 @@ printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; - PyAsyncMethods *tp_as_async; /* formerly known as tp_compare or tp_reserved */ + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2) + or tp_reserved (Python 3) */ reprfunc tp_repr; /* Method suites for standard classes */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Aug 26 20:09:45 2015 From: python-checkins at python.org (eric.smith) Date: Wed, 26 Aug 2015 18:09:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_an_incorrect_comment?= =?utf-8?q?=2E?= Message-ID: <20150826180935.67820.17121@psf.io> https://hg.python.org/cpython/rev/1f94fec31265 changeset: 97516:1f94fec31265 user: Eric V. Smith date: Wed Aug 26 14:10:32 2015 -0400 summary: Fixed an incorrect comment. files: Objects/stringlib/unicode_format.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h --- a/Objects/stringlib/unicode_format.h +++ b/Objects/stringlib/unicode_format.h @@ -67,7 +67,7 @@ return PyUnicode_Substring(str->str, str->start, str->end); } -/* return a new string. if str->str is NULL, return None */ +/* return a new string. if str->str is NULL, return a new empty string */ Py_LOCAL_INLINE(PyObject *) SubString_new_object_or_empty(SubString *str) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 02:17:14 2015 From: python-checkins at python.org (eric.smith) Date: Thu, 27 Aug 2015 00:17:14 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_trivial_typos=2E?= Message-ID: <20150827001709.19638.37895@psf.io> https://hg.python.org/peps/rev/56a596c84e26 changeset: 5991:56a596c84e26 user: Eric V. Smith date: Wed Aug 26 20:17:12 2015 -0400 summary: Fix trivial typos. files: pep-0501.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -395,7 +395,7 @@ field_values[expr] = values[field_num] return field_values -And would could then be invoked as:: +And could then be invoked as:: # _ = i18n at top of module or injected into the builtins module print(_(i"This is a $translated $message")) @@ -469,7 +469,7 @@ templates can be prerendered with ``str``, rather than delegating the rendering to the called function. -This reflects the key difference from PEP 498, which *always* eagerly applies] +This reflects the key difference from PEP 498, which *always* eagerly applies the default rendering, without any convenient way to decide to do something different. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 03:24:06 2015 From: python-checkins at python.org (donald.stufft) Date: Thu, 27 Aug 2015 01:24:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_470?= Message-ID: <20150827012357.79911.67773@psf.io> https://hg.python.org/peps/rev/7701886b0b4f changeset: 5992:7701886b0b4f user: Donald Stufft date: Wed Aug 26 21:23:54 2015 -0400 summary: Update PEP 470 files: pep-0470.txt | 276 +++++++++++--------------------------- 1 files changed, 81 insertions(+), 195 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -1,36 +1,25 @@ PEP: 470 -Title: Using Multi Repository Support for External to PyPI Package File Hosting +Title: Removing External Hosting support on PyPI Version: $Revision$ Last-Modified: $Date$ Author: Donald Stufft , -BDFL-Delegate: Richard Jones +BDFL-Delegate: TBD Discussions-To: distutils-sig at python.org Status: Draft Type: Process Content-Type: text/x-rst Created: 12-May-2014 -Post-History: 14-May-2014, 05-Jun-2014, 03-Oct-2014, 13-Oct-2014 +Post-History: 14-May-2014, 05-Jun-2014, 03-Oct-2014, 13-Oct-2014, 26-Aug-2015 Replaces: 438 Abstract ======== -This PEP proposes a mechanism for project authors to register with PyPI an -external repository where their project's downloads can be located. This -information can than be included as part of the simple API so that installers -can use it to tell users where the item they are attempting to install is -located and what they need to do to enable this additional repository. In -addition to adding discovery information to make explicit multiple repositories -easy to use, this PEP also deprecates and removes the implicit multiple -repository support which currently functions through directly or indirectly -linking off site via the simple API. Finally this PEP also proposes deprecating -and removing the functionality added by PEP 438, particularly the additional -rel information and the meta tag to indicate the API version. - -This PEP *does* not propose mandating that all authors upload their projects to -PyPI in order to exist in the index nor does it propose any change to the human -facing elements of PyPI. +This PEP proposes the deprecation and removal of support for hosting files +externally to PyPI as well as the deprecation and removal of the functionality +added by PEP 438, particularly rel information to classify different types of +links and the meta-tag to indicate API version. Rationale @@ -65,14 +54,6 @@ often times do not realize who they need to contact in order to get this fixed or what their remediation steps are. -By moving to using explicit multiple repositories we can make the lines between -these two roles much more explicit and remove the "hidden" surprises caused by -the current implementation of handling people who do not want to use PyPI as a -repository. However simply moving to explicit multiple repositories is a -regression in discoverability, and for that reason this PEP adds an extension -to the current simple API which will enable easy discovery of the specific -repository that a project can be found in. - PEP 438 attempted to solve this issue by allowing projects to explicitly declare if they were using the repository features or not, and if they were not, it had the installers classify the links it found as either "internal", @@ -85,16 +66,17 @@ PyPI providing speed ups for a lot of people, however it did so by introducing a new point of confusion and pain for both the end users and the authors. +By moving to using explicit multiple repositories we can make the lines between +these two roles much more explicit and remove the "hidden" surprises caused by +the current implementation of handling people who do not want to use PyPI as a +repository. + Key User Experience Expectations -------------------------------- #. Easily allow external hosting to "just work" when appropriately configured at the system, user or virtual environment level. -#. Easily allow package authors to tell PyPI "my releases are hosted " - and have that advertised in such a way that tools can clearly communicate it - to users, without silently introducing unexpected dependencies on third - party services. #. Eliminate any and all references to the confusing "verifiable external" and "unverifiable external" distinction from the user experience (both when installing and when releasing packages). @@ -122,7 +104,7 @@ likely that someone is already familiar with the concept. Additionally, the multiple repository approach is a concept that is useful -outside of the narrow scope of allowing projects which wish to be included on +outside of the narrow scope of allowing projects that wish to be included on the index portion of PyPI but do not wish to utilize the repository portion of PyPI. This includes places where a company may wish to host a repository that contains their internal packages or where a project may wish to have multiple @@ -215,64 +197,9 @@ individual implementation. -External Index Discovery -======================== - -One of the problems with using an additional index is one of discovery. Users -will not generally be aware that an additional index is required at all much -less where that index can be found. Projects can attempt to convey this -information using their description on the PyPI page however that excludes -people who discover their project organically through ``pip search``. - -To support projects that wish to externally host their files and to enable -users to easily discover what additional indexes are required, PyPI will gain -the ability for projects to register external index URLs along with an -associated comment for each. These URLs will be made available on the simple -page however they will not be linked or provided in a form that older -installers will automatically search them. - -This ability will take the form of a ```` tag. The name of this tag must -be set to ``repository`` or ``find-link`` and the content will be a link to the -location of the repository. An optional data-description attribute will convey -any comments or description that the author has provided. - -An example would look something like:: - - - - - -When an installer fetches the simple page for a project, if it finds this -additional meta-data then it should use this data to tell the user how to add -one or more of the additional URLs to search in. This message should include -any comments that the project has included to enable them to communicate to the -user and provide hints as to which URL they might want (e.g. if some are only -useful or compatible with certain platforms or situations). When the installer -has implemented the auto discovery mechanisms they should also deprecate any of -the mechanisms added for PEP 438 (such as ``--allow-external``) for removal at -the end of the deprecation period proposed by the PEP. - -In addition to the API for programtic access to the registered external -repositories, PyPI will also prevent these URLs in the UI so that users with -an installer that does not implement the discovery mechanism can still easily -discover what repository the project is using to host itself. - -This feature **MUST** be added to PyPI and be contained in a released version -of pip prior to starting the deprecation and removal process for the implicit -offsite hosting functionality. - - Deprecation and Removal of Link Spidering ========================================= -.. important:: The deprecation specified in this section **MUST** not start to - until after the discovery mechanisms have been implemented and released in - pip. - - The only exception to this is the addition of the ``pypi-only`` mode and - defaulting new projects to it without abilility to switch to a different - mode. - A new hosting mode will be added to PyPI. This hosting mode will be called ``pypi-only`` and will be in addition to the three that PEP 438 has already given us which are ``pypi-explicit``, ``pypi-scrape``, ``pypi-scrape-crawl``. @@ -282,44 +209,34 @@ Upon acceptance of this PEP and the addition of the ``pypi-only`` mode, all new projects will be defaulted to the PyPI only mode and they will be locked to -this mode and unable to change this particular setting. ``pypi-only`` projects -will still be able to register external index URLs as described above - the -"pypi-only" refers only to the download links that are published directly on -PyPI. +this mode and unable to change this particular setting. An email will then be sent out to all of the projects which are hosted only on PyPI informing them that in one month their project will be automatically converted to the ``pypi-only`` mode. A month after these emails have been sent any of those projects which were emailed, which still are hosted only on PyPI -will have their mode set to ``pypi-only``. +will have their mode set permanently to ``pypi-only``. -After that switch, an email will be sent to projects which rely on hosting +At the same time, an email will be sent to projects which rely on hosting external to PyPI. This email will warn these projects that externally hosted -files have been deprecated on PyPI and that in 6 months from the time of that +files have been deprecated on PyPI and that in 3 months from the time of that email that all external links will be removed from the installer APIs. This email **MUST** include instructions for converting their projects to be hosted on PyPI and **MUST** include links to a script or package that will enable them to enter their PyPI credentials and package name and have it automatically download and re-host all of their files on PyPI. This email **MUST** also -include instructions for setting up their own index page and registering that -with PyPI, including the fact that they can use pythonhosted.org as a host for -an index page without requiring them to host any additional infrastructure or -purchase a TLS certificate. This email must also contain a link to the Terms of -Service for PyPI as many users may have signed up a long time ago and may not -recall what those terms are. Finally this email must also contain a list of -the links registered with PyPI where we were able to detect an installable file -was located. +include instructions for setting up their own index page. This email must also contain a link to the Terms of Service for PyPI as many users may have signed +up a long time ago and may not recall what those terms are. Finally this email +must also contain a list of the links registered with PyPI where we were able +to detect an installable file was located. -Five months after the initial email, another email must be sent to any projects +Two months after the initial email, another email must be sent to any projects still relying on external hosting. This email will include all of the same information that the first email contained, except that the removal date will -be one month away instead of six. +be one month away instead of three. Finally a month later all projects will be switched to the ``pypi-only`` mode -and PyPI will be modified to remove the externally linked files functionality, -when switching these projects to the ``pypi-only`` mode we will move any links -which are able to be used for discovering other projects automatically to as -an external repository. +and PyPI will be modified to remove the externally linked files functionality. Summary of Changes @@ -328,116 +245,85 @@ Repository side --------------- -#. Implement simple API changes to allow the addition of an external +#. Deprecate and remove the hosting modes as defined by PEP 438. +#. Restrict simple API to only list the files that are contained within the repository. -#. *(Optional, Mandatory on PyPI)* Deprecate and remove the hosting modes as - defined by PEP 438. -#. *(Optional, Mandatory on PyPI)* Restrict simple API to only list the files - that are contained within the repository and the external repository - metadata. + Client side ----------- #. Implement multiple repository support. #. Implement some mechanism for removing/disabling the default repository. -#. Implement the discovery mechanism. -#. *(Optional)* Deprecate / Remove PEP 438 +#. Deprecate / Remove PEP 438 Impact ====== -The large impact of this PEP will be that for users of older installation -clients they will not get a discovery mechanism built into the install command. -This will require them to browse to the PyPI web UI and discover the repository -there. Since any URLs required to instal a project will be automatically -migrated to the new format, the biggest change to users will be requiring a new -option to install these projects. +To determine impact, we've looked at all projects using a method of searching +PyPI which is similar to what pip and setuptools use and searched for all +files available on PyPI, safely linked from PyPI, unsafely linked from PyPI, +and finally unsafely available outside of PyPI. When the same file was found +in multiple locations it was deduplicated and only counted it in one location +based on the following preferences: PyPI > Safely Off PyPI > Unsafely Off PyPI. +This gives us the broadest possible definition of impact, it means that any +single file for this project may no longer be visible by default, however that +file could be years old, or it could be a binary file while there is a sdist +available on PyPI. This means that the *real* impact will likely be much +smaller, but in an attempt not to miscount we take the broadest possible +definition. -Looking at the numbers the actual impact should be quite low, with it affecting -just 3.8% of projects which host any files only externally or 2.2% which have -their latest version hosted only externally. +At the time of this writing there are 65,232 projects hosted on PyPI and of +those, 59 of them rely on external files that are safely hosted outside of PyPI +and 931 of them rely on external files which are unsafely hosted outside of +PyPI. This shows us that 1.5% of projects will be affected in some way by this +change while 98.5% will continue to function as they always have. In addition, +only 5% of the projects affected are using the features provided by PEP 438 to +safely host outside of PyPI while 95% of them are exposing their users to +Remote Code Execution via a Man In The Middle attack. -6674 unique IP addresses have accessed the Simple API for these 3.8% of -projects in a single day (2014-09-30). Of those, 99.5% of them installed -something which could not be verified, and thus they were open to a Remote Code -Execution via a Man-In-The-Middle attack, while 7.9% installed something which -could be verified and only 0.4% only installed things which could be verified. -This means that 99.5% users of these features, both new and old, are doing -something unsafe, and for anything using an older copy of pip or using -setuptools at all they are silently unsafe. +Data Sovereignty +================ +In the discussions around previous versions of this PEP, one of the key use +cases for wanting to host files externally to PyPI was due to data sovereignty +requirements for people living in jurisdictions outside of the USA, where PyPI +is currently hosted. The author of this PEP is not blind to these concerns and +realizes that this PEP represents a regression for the people that have these +concerns, however the current situation is presenting an extremely poor user +experience and the feature is only being used by a small percentage of +projects. In addition, the data sovereignty problems requires familarity with +the laws outside of the home jurisdiction of the author of this PEP, who is +also the principal developer and operator of PyPI. For these reasons, a +solution for the problem of data sovereignty has been deferred and is +considered outside of the scope for this PEP. -Projects Which Rely on Externally Hosted files ----------------------------------------------- - -This is determined by crawling the simple index and looking for installable -files using a similar detection method as pip and setuptools use. The "latest" -version is determined using ``pkg_resources.parse_version`` sort order and it -is used to show whether or not the latest version is hosted externally or only -old versions are. - -============ ======= ================ =================== ======= -\ PyPI External (old) External (latest) Total -============ ======= ================ =================== ======= - **Safe** 43313 16 39 43368 - **Unsafe** 0 756 1092 1848 - **Total** 43313 772 1131 45216 -============ ======= ================ =================== ======= - - -Top Externally Hosted Projects by Requests ------------------------------------------- - -This is determined by looking at the number of requests the -``/simple//`` page had gotten in a single day. The total number of -requests during that day was 10,623,831. - -============================== ======== -Project Requests -============================== ======== -PIL 63869 -Pygame 2681 -mysql-connector-python 1562 -pyodbc 724 -elementtree 635 -salesforce-python-toolkit 316 -wxPython 295 -PyXML 251 -RBTools 235 -python-graph-core 123 -cElementTree 121 -============================== ======== - - -Top Externally Hosted Projects by Unique IPs --------------------------------------------- - -This is determined by looking at the IP addresses of requests the -``/simple//`` page had gotten in a single day. The total number of -unique IP addresses during that day was 124,604. - -============================== ========== -Project Unique IPs -============================== ========== -PIL 4553 -mysql-connector-python 462 -Pygame 202 -pyodbc 181 -elementtree 166 -wxPython 126 -RBTools 114 -PyXML 87 -salesforce-python-toolkit 76 -pyDes 76 -============================== ========== +If someone for whom the issue of data sovereignty matters to them wishes to +put forth the effort, then at that time a system can be designed, implemented, +and ultimately deployed and operated that would satisfy both the needs of non +US users that cannot upload their projects to a system on US soil and the +quality of user experience that is attempted to be created on PyPI. Rejected Proposals ================== +Allow easier discovery of externally hosted indexes +--------------------------------------------------- + +A previous version of this PEP included a new feature added to both PyPI and +installers that would allow project authors to enter into PyPI a list of +URLs that would instruct installers to ignore any files uploaded to PyPI and +instead return an error telling the end user about these extra URLs that they +can add to their installer to make the installation work. + +This idea is rejected because it provides a similar painful end user experience +where people will first attempt to install something, get an error, then have +to re-run the installation with the correct options. + + Keep the current classification system but adjust the options ------------------------------------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 03:56:09 2015 From: python-checkins at python.org (donald.stufft) Date: Thu, 27 Aug 2015 01:56:09 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Better_capitalization_of_titl?= =?utf-8?q?e?= Message-ID: <20150827015607.67848.50578@psf.io> https://hg.python.org/peps/rev/3a32e704e274 changeset: 5993:3a32e704e274 user: Donald Stufft date: Wed Aug 26 21:56:04 2015 -0400 summary: Better capitalization of title files: pep-0470.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -1,5 +1,5 @@ PEP: 470 -Title: Removing External Hosting support on PyPI +Title: Removing External Hosting Support on PyPI Version: $Revision$ Last-Modified: $Date$ Author: Donald Stufft , -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 04:24:59 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 27 Aug 2015 02:24:59 +0000 Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_merge?= Message-ID: <20150827022459.22342.72078@psf.io> https://hg.python.org/peps/rev/703362f559ee changeset: 5995:703362f559ee parent: 5994:896a37b7c7eb parent: 5993:3a32e704e274 user: Alexander Belopolsky date: Wed Aug 26 22:24:54 2015 -0400 summary: merge files: pep-0470.txt | 276 +++++++++++--------------------------- 1 files changed, 81 insertions(+), 195 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -1,36 +1,25 @@ PEP: 470 -Title: Using Multi Repository Support for External to PyPI Package File Hosting +Title: Removing External Hosting Support on PyPI Version: $Revision$ Last-Modified: $Date$ Author: Donald Stufft , -BDFL-Delegate: Richard Jones +BDFL-Delegate: TBD Discussions-To: distutils-sig at python.org Status: Draft Type: Process Content-Type: text/x-rst Created: 12-May-2014 -Post-History: 14-May-2014, 05-Jun-2014, 03-Oct-2014, 13-Oct-2014 +Post-History: 14-May-2014, 05-Jun-2014, 03-Oct-2014, 13-Oct-2014, 26-Aug-2015 Replaces: 438 Abstract ======== -This PEP proposes a mechanism for project authors to register with PyPI an -external repository where their project's downloads can be located. This -information can than be included as part of the simple API so that installers -can use it to tell users where the item they are attempting to install is -located and what they need to do to enable this additional repository. In -addition to adding discovery information to make explicit multiple repositories -easy to use, this PEP also deprecates and removes the implicit multiple -repository support which currently functions through directly or indirectly -linking off site via the simple API. Finally this PEP also proposes deprecating -and removing the functionality added by PEP 438, particularly the additional -rel information and the meta tag to indicate the API version. - -This PEP *does* not propose mandating that all authors upload their projects to -PyPI in order to exist in the index nor does it propose any change to the human -facing elements of PyPI. +This PEP proposes the deprecation and removal of support for hosting files +externally to PyPI as well as the deprecation and removal of the functionality +added by PEP 438, particularly rel information to classify different types of +links and the meta-tag to indicate API version. Rationale @@ -65,14 +54,6 @@ often times do not realize who they need to contact in order to get this fixed or what their remediation steps are. -By moving to using explicit multiple repositories we can make the lines between -these two roles much more explicit and remove the "hidden" surprises caused by -the current implementation of handling people who do not want to use PyPI as a -repository. However simply moving to explicit multiple repositories is a -regression in discoverability, and for that reason this PEP adds an extension -to the current simple API which will enable easy discovery of the specific -repository that a project can be found in. - PEP 438 attempted to solve this issue by allowing projects to explicitly declare if they were using the repository features or not, and if they were not, it had the installers classify the links it found as either "internal", @@ -85,16 +66,17 @@ PyPI providing speed ups for a lot of people, however it did so by introducing a new point of confusion and pain for both the end users and the authors. +By moving to using explicit multiple repositories we can make the lines between +these two roles much more explicit and remove the "hidden" surprises caused by +the current implementation of handling people who do not want to use PyPI as a +repository. + Key User Experience Expectations -------------------------------- #. Easily allow external hosting to "just work" when appropriately configured at the system, user or virtual environment level. -#. Easily allow package authors to tell PyPI "my releases are hosted " - and have that advertised in such a way that tools can clearly communicate it - to users, without silently introducing unexpected dependencies on third - party services. #. Eliminate any and all references to the confusing "verifiable external" and "unverifiable external" distinction from the user experience (both when installing and when releasing packages). @@ -122,7 +104,7 @@ likely that someone is already familiar with the concept. Additionally, the multiple repository approach is a concept that is useful -outside of the narrow scope of allowing projects which wish to be included on +outside of the narrow scope of allowing projects that wish to be included on the index portion of PyPI but do not wish to utilize the repository portion of PyPI. This includes places where a company may wish to host a repository that contains their internal packages or where a project may wish to have multiple @@ -215,64 +197,9 @@ individual implementation. -External Index Discovery -======================== - -One of the problems with using an additional index is one of discovery. Users -will not generally be aware that an additional index is required at all much -less where that index can be found. Projects can attempt to convey this -information using their description on the PyPI page however that excludes -people who discover their project organically through ``pip search``. - -To support projects that wish to externally host their files and to enable -users to easily discover what additional indexes are required, PyPI will gain -the ability for projects to register external index URLs along with an -associated comment for each. These URLs will be made available on the simple -page however they will not be linked or provided in a form that older -installers will automatically search them. - -This ability will take the form of a ```` tag. The name of this tag must -be set to ``repository`` or ``find-link`` and the content will be a link to the -location of the repository. An optional data-description attribute will convey -any comments or description that the author has provided. - -An example would look something like:: - - - - - -When an installer fetches the simple page for a project, if it finds this -additional meta-data then it should use this data to tell the user how to add -one or more of the additional URLs to search in. This message should include -any comments that the project has included to enable them to communicate to the -user and provide hints as to which URL they might want (e.g. if some are only -useful or compatible with certain platforms or situations). When the installer -has implemented the auto discovery mechanisms they should also deprecate any of -the mechanisms added for PEP 438 (such as ``--allow-external``) for removal at -the end of the deprecation period proposed by the PEP. - -In addition to the API for programtic access to the registered external -repositories, PyPI will also prevent these URLs in the UI so that users with -an installer that does not implement the discovery mechanism can still easily -discover what repository the project is using to host itself. - -This feature **MUST** be added to PyPI and be contained in a released version -of pip prior to starting the deprecation and removal process for the implicit -offsite hosting functionality. - - Deprecation and Removal of Link Spidering ========================================= -.. important:: The deprecation specified in this section **MUST** not start to - until after the discovery mechanisms have been implemented and released in - pip. - - The only exception to this is the addition of the ``pypi-only`` mode and - defaulting new projects to it without abilility to switch to a different - mode. - A new hosting mode will be added to PyPI. This hosting mode will be called ``pypi-only`` and will be in addition to the three that PEP 438 has already given us which are ``pypi-explicit``, ``pypi-scrape``, ``pypi-scrape-crawl``. @@ -282,44 +209,34 @@ Upon acceptance of this PEP and the addition of the ``pypi-only`` mode, all new projects will be defaulted to the PyPI only mode and they will be locked to -this mode and unable to change this particular setting. ``pypi-only`` projects -will still be able to register external index URLs as described above - the -"pypi-only" refers only to the download links that are published directly on -PyPI. +this mode and unable to change this particular setting. An email will then be sent out to all of the projects which are hosted only on PyPI informing them that in one month their project will be automatically converted to the ``pypi-only`` mode. A month after these emails have been sent any of those projects which were emailed, which still are hosted only on PyPI -will have their mode set to ``pypi-only``. +will have their mode set permanently to ``pypi-only``. -After that switch, an email will be sent to projects which rely on hosting +At the same time, an email will be sent to projects which rely on hosting external to PyPI. This email will warn these projects that externally hosted -files have been deprecated on PyPI and that in 6 months from the time of that +files have been deprecated on PyPI and that in 3 months from the time of that email that all external links will be removed from the installer APIs. This email **MUST** include instructions for converting their projects to be hosted on PyPI and **MUST** include links to a script or package that will enable them to enter their PyPI credentials and package name and have it automatically download and re-host all of their files on PyPI. This email **MUST** also -include instructions for setting up their own index page and registering that -with PyPI, including the fact that they can use pythonhosted.org as a host for -an index page without requiring them to host any additional infrastructure or -purchase a TLS certificate. This email must also contain a link to the Terms of -Service for PyPI as many users may have signed up a long time ago and may not -recall what those terms are. Finally this email must also contain a list of -the links registered with PyPI where we were able to detect an installable file -was located. +include instructions for setting up their own index page. This email must also contain a link to the Terms of Service for PyPI as many users may have signed +up a long time ago and may not recall what those terms are. Finally this email +must also contain a list of the links registered with PyPI where we were able +to detect an installable file was located. -Five months after the initial email, another email must be sent to any projects +Two months after the initial email, another email must be sent to any projects still relying on external hosting. This email will include all of the same information that the first email contained, except that the removal date will -be one month away instead of six. +be one month away instead of three. Finally a month later all projects will be switched to the ``pypi-only`` mode -and PyPI will be modified to remove the externally linked files functionality, -when switching these projects to the ``pypi-only`` mode we will move any links -which are able to be used for discovering other projects automatically to as -an external repository. +and PyPI will be modified to remove the externally linked files functionality. Summary of Changes @@ -328,116 +245,85 @@ Repository side --------------- -#. Implement simple API changes to allow the addition of an external +#. Deprecate and remove the hosting modes as defined by PEP 438. +#. Restrict simple API to only list the files that are contained within the repository. -#. *(Optional, Mandatory on PyPI)* Deprecate and remove the hosting modes as - defined by PEP 438. -#. *(Optional, Mandatory on PyPI)* Restrict simple API to only list the files - that are contained within the repository and the external repository - metadata. + Client side ----------- #. Implement multiple repository support. #. Implement some mechanism for removing/disabling the default repository. -#. Implement the discovery mechanism. -#. *(Optional)* Deprecate / Remove PEP 438 +#. Deprecate / Remove PEP 438 Impact ====== -The large impact of this PEP will be that for users of older installation -clients they will not get a discovery mechanism built into the install command. -This will require them to browse to the PyPI web UI and discover the repository -there. Since any URLs required to instal a project will be automatically -migrated to the new format, the biggest change to users will be requiring a new -option to install these projects. +To determine impact, we've looked at all projects using a method of searching +PyPI which is similar to what pip and setuptools use and searched for all +files available on PyPI, safely linked from PyPI, unsafely linked from PyPI, +and finally unsafely available outside of PyPI. When the same file was found +in multiple locations it was deduplicated and only counted it in one location +based on the following preferences: PyPI > Safely Off PyPI > Unsafely Off PyPI. +This gives us the broadest possible definition of impact, it means that any +single file for this project may no longer be visible by default, however that +file could be years old, or it could be a binary file while there is a sdist +available on PyPI. This means that the *real* impact will likely be much +smaller, but in an attempt not to miscount we take the broadest possible +definition. -Looking at the numbers the actual impact should be quite low, with it affecting -just 3.8% of projects which host any files only externally or 2.2% which have -their latest version hosted only externally. +At the time of this writing there are 65,232 projects hosted on PyPI and of +those, 59 of them rely on external files that are safely hosted outside of PyPI +and 931 of them rely on external files which are unsafely hosted outside of +PyPI. This shows us that 1.5% of projects will be affected in some way by this +change while 98.5% will continue to function as they always have. In addition, +only 5% of the projects affected are using the features provided by PEP 438 to +safely host outside of PyPI while 95% of them are exposing their users to +Remote Code Execution via a Man In The Middle attack. -6674 unique IP addresses have accessed the Simple API for these 3.8% of -projects in a single day (2014-09-30). Of those, 99.5% of them installed -something which could not be verified, and thus they were open to a Remote Code -Execution via a Man-In-The-Middle attack, while 7.9% installed something which -could be verified and only 0.4% only installed things which could be verified. -This means that 99.5% users of these features, both new and old, are doing -something unsafe, and for anything using an older copy of pip or using -setuptools at all they are silently unsafe. +Data Sovereignty +================ +In the discussions around previous versions of this PEP, one of the key use +cases for wanting to host files externally to PyPI was due to data sovereignty +requirements for people living in jurisdictions outside of the USA, where PyPI +is currently hosted. The author of this PEP is not blind to these concerns and +realizes that this PEP represents a regression for the people that have these +concerns, however the current situation is presenting an extremely poor user +experience and the feature is only being used by a small percentage of +projects. In addition, the data sovereignty problems requires familarity with +the laws outside of the home jurisdiction of the author of this PEP, who is +also the principal developer and operator of PyPI. For these reasons, a +solution for the problem of data sovereignty has been deferred and is +considered outside of the scope for this PEP. -Projects Which Rely on Externally Hosted files ----------------------------------------------- - -This is determined by crawling the simple index and looking for installable -files using a similar detection method as pip and setuptools use. The "latest" -version is determined using ``pkg_resources.parse_version`` sort order and it -is used to show whether or not the latest version is hosted externally or only -old versions are. - -============ ======= ================ =================== ======= -\ PyPI External (old) External (latest) Total -============ ======= ================ =================== ======= - **Safe** 43313 16 39 43368 - **Unsafe** 0 756 1092 1848 - **Total** 43313 772 1131 45216 -============ ======= ================ =================== ======= - - -Top Externally Hosted Projects by Requests ------------------------------------------- - -This is determined by looking at the number of requests the -``/simple//`` page had gotten in a single day. The total number of -requests during that day was 10,623,831. - -============================== ======== -Project Requests -============================== ======== -PIL 63869 -Pygame 2681 -mysql-connector-python 1562 -pyodbc 724 -elementtree 635 -salesforce-python-toolkit 316 -wxPython 295 -PyXML 251 -RBTools 235 -python-graph-core 123 -cElementTree 121 -============================== ======== - - -Top Externally Hosted Projects by Unique IPs --------------------------------------------- - -This is determined by looking at the IP addresses of requests the -``/simple//`` page had gotten in a single day. The total number of -unique IP addresses during that day was 124,604. - -============================== ========== -Project Unique IPs -============================== ========== -PIL 4553 -mysql-connector-python 462 -Pygame 202 -pyodbc 181 -elementtree 166 -wxPython 126 -RBTools 114 -PyXML 87 -salesforce-python-toolkit 76 -pyDes 76 -============================== ========== +If someone for whom the issue of data sovereignty matters to them wishes to +put forth the effort, then at that time a system can be designed, implemented, +and ultimately deployed and operated that would satisfy both the needs of non +US users that cannot upload their projects to a system on US soil and the +quality of user experience that is attempted to be created on PyPI. Rejected Proposals ================== +Allow easier discovery of externally hosted indexes +--------------------------------------------------- + +A previous version of this PEP included a new feature added to both PyPI and +installers that would allow project authors to enter into PyPI a list of +URLs that would instruct installers to ignore any files uploaded to PyPI and +instead return an error telling the end user about these extra URLs that they +can add to their installer to make the installation work. + +This idea is rejected because it provides a similar painful end user experience +where people will first attempt to install something, get an error, then have +to re-run the installation with the correct options. + + Keep the current classification system but adjust the options ------------------------------------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 04:24:59 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 27 Aug 2015 02:24:59 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_The_big_rename=2E_?= =?utf-8?b?IENoYW5nZWQgJ2ZpcnN0JyB0byAnZm9sZCcu?= Message-ID: <20150827022459.79911.30368@psf.io> https://hg.python.org/peps/rev/896a37b7c7eb changeset: 5994:896a37b7c7eb parent: 5991:56a596c84e26 user: Alexander Belopolsky date: Wed Aug 26 22:24:22 2015 -0400 summary: PEP 495: The big rename. Changed 'first' to 'fold'. files: pep-0495.txt | 278 +++++++++++++++++++++----------------- 1 files changed, 150 insertions(+), 128 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -14,9 +14,12 @@ Abstract ======== -This PEP adds a boolean member to the instances of ``datetime.time`` -and ``datetime.datetime`` classes that can be used to differentiate -between two moments in time for which local times are the same. +This PEP adds a new attribute ``fold`` to the instances of +``datetime.time`` and ``datetime.datetime`` classes that can be used +to differentiate between two moments in time for which local times are +the same. The allowed values for the `fold` attribute will be 0 and 1 +with 0 corresponding to the earlier and 1 to the later of the two +possible readings of an ambiguous local time. .. sidebar:: US public service advertisement @@ -29,13 +32,13 @@ ========= In the most world locations there have been and will be times when -local clocks are moved back. [#]_ In those times, intervals are introduced -in which local clocks show the same time twice in the same day. In -these situations, the information displayed on a local clock (or -stored in a Python datetime instance) is insufficient to identify a -particular moment in time. The proposed solution is to add a boolean -flag to the ``datetime`` instances that will distinguish between the -two ambiguous times. +local clocks are moved back. [#]_ In those times, intervals are +introduced in which local clocks show the same time twice in the same +day. In these situations, the information displayed on a local clock +(or stored in a Python datetime instance) is insufficient to identify +a particular moment in time. The proposed solution is to add an +attribute to the ``datetime`` instances taking values of 0 and 1 that +will enumerate the two ambiguous times. .. [#] People who live in locations observing the Daylight Saving Time (DST) move their clocks back (usually one hour) every Fall. @@ -54,28 +57,35 @@ Terminology =========== -When clocks are moved back, we say that a *fold* is created in time. +When clocks are moved back, we say that a *fold* [#]_ is created in time. When the clocks are moved forward, a *gap* is created. A local time that falls in the fold is called *ambiguous*. A local time that falls in the gap is called *missing*. +.. [#] The term "fall-backward fold" was invented in 1990s by Paul Eggert + of UCLA who used it in various Internet discussions related to the C language + standard that culminated in a `Defect Report #139`_. + +.. _Defect Report #139: http://www.open-std.org/jtc1/sc22/wg14/docs/rr/dr_136.html + + Proposal ======== -The "first" flag ----------------- +The "fold" attribute +-------------------- -We propose adding a boolean member called ``first`` to the instances -of ``datetime.time`` and ``datetime.datetime`` classes. This member -should have the value ``True`` for all instances except those that +We propose adding an attribute called ``fold`` to the instances +of ``datetime.time`` and ``datetime.datetime`` classes. This attribute +should have the value 0 for all instances except those that represent the second (chronologically) moment in time in an ambiguous -case. [#]_ +case. For those instances, the value will be 1. [#]_ -.. [#] An instance that has ``first=False`` in a non-ambiguous case is +.. [#] An instance that has ``fold=1`` in a non-ambiguous case is said to represent an invalid time (or is invalid for short), but users are not prevented from creating invalid instances by passing - ``first=False`` to a constructor or to a ``replace()`` method. This + ``fold=1`` to a constructor or to a ``replace()`` method. This is similar to the current situation with the instances that fall in the spring-forward gap. Such instances don't represent any valid time, but neither the constructors nor the ``replace()`` methods @@ -89,68 +99,68 @@ Attributes .......... -Instances of ``datetime.time`` and ``datetime.datetime`` will get a -new boolean attribute called "first." +Instances of ``datetime.time`` and ``datetime.datetime`` classes will +get a new attribute ``fold`` with two possible values: 0 and 1. Constructors ............ The ``__new__`` methods of the ``datetime.time`` and ``datetime.datetime`` classes will get a new keyword-only argument -called ``first`` with the default value ``True``. The value of the -``first`` argument will be used to initialize the value of the -``first`` attribute in the returned instance. +called ``fold`` with the default value 0. The value of the +``fold`` argument will be used to initialize the value of the +``fold`` attribute in the returned instance. Methods ....... The ``replace()`` methods of the ``datetime.time`` and ``datetime.datetime`` classes will get a new keyword-only argument -called ``first``. It will -behave similarly to the other ``replace()`` arguments: if the ``first`` -argument is specified and given a boolean value, the new instance -returned by ``replace()`` will have its ``first`` attribute set -to that value. In CPython, a non-boolean value of ``first`` will +called ``fold``. It will +behave similarly to the other ``replace()`` arguments: if the ``fold`` +argument is specified and given a value 0 or 1, the new instance +returned by ``replace()`` will have its ``fold`` attribute set +to that value. In CPython, any non-integer value of ``fold`` will raise a ``TypeError``, but other implementations may allow the value -``None`` to behave the same as when ``first`` is not given. If the -``first`` argument is not specified, the original value of the ``first`` +``None`` to behave the same as when ``fold`` is not given. If the +``fold`` argument is not specified, the original value of the ``fold`` attribute is copied to the result. C-API ..... -Access macros will be defined to extract the value of ``first`` from +Access macros will be defined to extract the value of ``fold`` from ``PyDateTime_DateTime`` and ``PyDateTime_Time`` objects. .. code:: - bool PyDateTime_GET_FIRST(PyDateTime_DateTime *o) + int PyDateTime_GET_FOLD(PyDateTime_DateTime *o) -Return the value of ``first`` as a C99 ``bool``. +Return the value of ``fold`` as a C ``int``. .. code:: - bool PyDateTime_TIME_GET_FIRST(PyDateTime_Time *o) + int PyDateTime_TIME_GET_FOLD(PyDateTime_Time *o) -Return the value of ``first`` as a C99 ``bool``. +Return the value of ``fold`` as a C ``int``. -Additional constructors will be defined that will take an additional -boolean argument to specify the value of ``first`` in the created +New constructors will be defined that will take an additional +argument to specify the value of ``fold`` in the created instance: .. code:: - PyObject* PyDateTime_FromDateAndTimeAndFirst(int year, int month, int day, int hour, int minute, int second, int usecond, bool first) + PyObject* PyDateTime_FromDateAndTimeAndFold(int year, int month, int day, int hour, int minute, int second, int usecond, int fold) Return a ``datetime.datetime`` object with the specified year, month, -day, hour, minute, second, microsecond and first. +day, hour, minute, second, microsecond and fold. .. code:: - PyObject* PyTime_FromTimeAndFirst(int hour, int minute, int second, int usecond, bool first) + PyObject* PyTime_FromTimeAndFold(int hour, int minute, int second, int usecond, int fold) Return a ``datetime.time`` object with the specified hour, minute, -second, microsecond and first. +second, microsecond and fold. Affected Behaviors @@ -160,19 +170,19 @@ ................ The ``datetime.now()`` method called with no arguments, will set -``first=False`` when returning the second of the two ambiguous times -in a fold. When called with a ``tzinfo`` argument, the value of the -``first`` will be determined by the ``tzinfo.fromutc()`` -implementation. If an instance of the built-in ``datetime.timezone`` -is passed as ``tzinfo``, the returned datetime instance will always -have ``first=True``. +``fold=1`` when returning the second of the two ambiguous times in a +system local time fold. When called with a ``tzinfo`` argument, the +value of the ``fold`` will be determined by the ``tzinfo.fromutc()`` +implementation. If an instance of the ``datetime.timezone`` class +(*e.g.* ``datetime.timezone.utc``) is passed as ``tzinfo``, the +returned datetime instance will always have ``fold=0``. Conversion from naive to aware .............................. The ``astimezone()`` method will now work for naive ``self``. The -system local timezone will be assumed in this case and the ``first`` +system local timezone will be assumed in this case and the ``fold`` flag will be used to determine which local timezone is in effect in the ambiguous case. @@ -181,7 +191,7 @@ >>> dt = datetime(2014, 11, 2, 1, 30) >>> dt.astimezone().strftime('%D %T %Z%z') '11/02/14 01:30:00 EDT-0400' - >>> dt.replace(first=False).astimezone().strftime('%D %T %Z%z') + >>> dt.replace(fold=1).astimezone().strftime('%D %T %Z%z') '11/02/14 01:30:00 EST-0500' @@ -189,14 +199,14 @@ ........................................ The ``fromtimestamp()`` static method of ``datetime.datetime`` will -set the ``first`` attribute appropriately in the returned object. +set the ``fold`` attribute appropriately in the returned object. For example, on a system set to US/Eastern timezone:: >>> datetime.fromtimestamp(1414906200) datetime.datetime(2014, 11, 2, 1, 30) >>> datetime.fromtimestamp(1414906200 + 3600) - datetime.datetime(2014, 11, 2, 1, 30, first=False) + datetime.datetime(2014, 11, 2, 1, 30, fold=1) Conversion to POSIX seconds from EPOCH @@ -204,7 +214,7 @@ The ``timestamp()`` method of ``datetime.datetime`` will return different values for ``datetime.datetime`` instances that differ only by the value -of their ``first`` attribute if and only if these instances represent an +of their ``fold`` attribute if and only if these instances represent an ambiguous or a missing time. When a ``datetime.datetime`` instance ``dt`` represents an ambiguous @@ -213,14 +223,14 @@ datetime.fromtimestamp(s0) == datetime.fromtimestamp(s1) == dt In this case, ``dt.timestamp()`` will return the smaller of ``s0`` -and ``s1`` values if ``dt.first == True`` and the larger otherwise. +and ``s1`` values if ``dt.fold == True`` and the larger otherwise. For example, on a system set to US/Eastern timezone:: - >>> datetime(2014, 11, 2, 1, 30, first=True).timestamp() + >>> datetime(2014, 11, 2, 1, 30, fold=0).timestamp() 1414906200.0 - >>> datetime(2014, 11, 2, 1, 30, first=False).timestamp() + >>> datetime(2014, 11, 2, 1, 30, fold=1).timestamp() 1414909800.0 @@ -237,14 +247,14 @@ is always the same as the offset right after the gap. The value returned by ``dt.timestamp()`` given a missing -``dt`` will be the larger of the two "nice to know" values -if ``dt.first == True`` and the smaller otherwise. +``dt`` will be the greater of the two "nice to know" values +if ``dt.fold == 0`` and the smaller otherwise. For example, on a system set to US/Eastern timezone:: - >>> datetime(2015, 3, 8, 2, 30, first=True).timestamp() + >>> datetime(2015, 3, 8, 2, 30, fold=0).timestamp() 1425799800.0 - >>> datetime(2015, 3, 8, 2, 30, first=False).timestamp() + >>> datetime(2015, 3, 8, 2, 30, fold=1).timestamp() 1425796200.0 @@ -252,36 +262,35 @@ ..................................... The ``datetime.datetime.combine()`` method will copy the value of the -``first`` attribute to the resulting ``datetime.datetime`` instance. +``fold`` attribute to the resulting ``datetime.datetime`` instance. The ``datetime.datetime.time()`` method will copy the value of the -``first`` attribute to the resulting ``datetime.time`` instance. +``fold`` attribute to the resulting ``datetime.time`` instance. Pickles ....... Pickle sizes for the ``datetime.datetime`` and ``datetime.time`` -objects will not change. The ``first`` flag will be encoded in the +objects will not change. The ``fold`` value will be encoded in the first bit of the 5th byte of the ``datetime.datetime`` pickle payload or the 2nd byte of the datetime.time. In the `current implementation`_ these bytes are used to store minute value (0-59) and the first bit is -always 0. Note that ``first=True`` will be encoded as 0 in the first -bit and ``first=False`` as 1. (This change only affects pickle -format. In the C implementation, the "first" member will get a full byte -to store the actual boolean value.) - +always 0. (This change only affects pickle format. In the C +implementation, the ``fold`` attribute will get a full byte to store its +value.) .. _current implementation: https://hg.python.org/cpython/file/d3b20bff9c5d/Include/datetime.h#l17 -Implementations of tzinfo in stdlib -=================================== + +Implementations of tzinfo in the Standard Library +================================================= No new implementations of ``datetime.tzinfo`` abstract class are proposed in this PEP. The existing (fixed offset) timezones do not introduce ambiguous local times and their ``utcoffset()`` implementation will return the same constant value as they do now -regardless of the value of ``first``. +regardless of the value of ``fold``. The basic implementation of ``fromutc()`` in the abstract ``datetime.tzinfo`` class will not change. It is currently not @@ -302,7 +311,7 @@ ------------------ New implementations of ``utcoffset()``, ``tzname()`` and ``dst()`` -methods should ignore the value of ``first`` unless they are called on +methods should ignore the value of ``fold`` unless they are called on the ambiguous or missing times. @@ -312,15 +321,15 @@ New subclasses should override the base-class ``fromutc()`` method and implement it so that in all cases where two UTC times ``u1`` and ``u2`` (``u1`` <``u2``) correspond to the same local time -``fromutc(u1)`` will return an instance with ``first=True`` and -``fromutc(u2)`` will return an instance with ``first=False``. In all -other cases the returned instance should have ``first=True``. +``fromutc(u1)`` will return an instance with ``fold=0`` and +``fromutc(u2)`` will return an instance with ``fold=1``. In all +other cases the returned instance should have ``fold=0``. On an ambiguous time introduced at the end of DST, the values returned by ``utcoffset()`` and ``dst()`` methods should be as follows +-----------------+----------------+------------------+ -| | first=True | first=False | +| | fold=0 | fold=1 | +=================+================+==================+ | utcoffset() | stdoff + dstoff| stdoff | +-----------------+----------------+------------------+ @@ -339,7 +348,7 @@ by ``utcoffset()`` and ``dst()`` methods should be as follows +-----------------+----------------+------------------+ -| | first=True | first=False | +| | fold=0 | fold=1 | +=================+================+==================+ | utcoffset() | stdoff | stdoff + dstoff | +-----------------+----------------+------------------+ @@ -352,11 +361,11 @@ On ambiguous/missing times introduced by the change in the standard time offset, the ``dst()`` method should return the same value regardless of -the value of ``first`` and the ``utcoffset()`` should return values +the value of ``fold`` and the ``utcoffset()`` should return values according to the following table: +-----------------+----------------+-----------------------------+ -| | first=True | first=False | +| | fold=0 | fold=1 | +=================+================+=============================+ | ambiguous | oldoff | newoff = oldoff - delta | +-----------------+----------------+-----------------------------+ @@ -369,23 +378,23 @@ Temporal Arithmetic =================== -The value of "first" will be ignored in all operations except those +The value of "fold" will be ignored in all operations except those that involve conversion between timezones. [#]_ As a consequence, ``datetime.datetime`` or ``datetime.time`` instances that differ only -by the value of ``first`` will compare as equal. Applications that +by the value of ``fold`` will compare as equal. Applications that need to differentiate between such instances should check the value of -``first`` or convert them to a timezone that does not have ambiguous +``fold`` or convert them to a timezone that does not have ambiguous times. The result of addition (subtraction) of a timedelta to (from) a -datetime will always have ``first`` set to ``True`` even if the -original datetime instance had ``first=False``. +datetime will always have ``fold`` set to 0 even if the +original datetime instance had ``fold=1``. .. [#] Computing a difference between two aware datetime instances with different values of ``tzinfo`` involves an implicit timezone conversion. In this case, the result may depend on the value of - the ``first`` flag in either of the instances, but only if the - instance has ``tzinfo`` that accounts for the value of ``first`` + the ``fold`` attribute in either of the instances, but only if the + instance has ``tzinfo`` that accounts for the value of ``fold`` in its ``utcoffset()`` method. @@ -393,16 +402,16 @@ ================================== This proposal will have little effect on the programs that do not read -the ``first`` flag explicitly or use tzinfo implementations that do. +the ``fold`` flag explicitly or use tzinfo implementations that do. The only visible change for such programs will be that conversions to and from POSIX timestamps will now round-trip correctly (up to floating point rounding). Programs that implemented a work-around to the old incorrect behavior may need to be modified. Pickles produced by older programs will remain fully forward -compatible. Only datetime/time instances with ``first=False`` pickled +compatible. Only datetime/time instances with ``fold=1`` pickled in the new versions will become unreadable by the older Python -versions. Pickles of instances with ``first=True`` (which is the +versions. Pickles of instances with ``fold=0`` (which is the default) will remain unchanged. @@ -428,6 +437,17 @@ ------- +(same characters, an hour later) + +------- + +* Bob: Alice - this Py-O-Clock gadget of mine asks me to choose + between fold=0 and fold=1 when I set it for tomorrow 01:30 AM. + What should I do? +* Alice: I've never hear of a Py-O-Clock, but I guess fold=0 is + the first 01:30 AM and fold=1 is the second. + + A technical reason .................. @@ -448,35 +468,37 @@ ``time.mktime`` is made, the only sane choice is usually ``tm_isdst=-1``. -Unlike ``tm_isdst``, the proposed ``first`` flag has no effect on the -interpretation of the datetime instance unless without that flag two -(or no) interpretations are possible. +Unlike ``tm_isdst``, the proposed ``fold`` attribute has no effect on +the interpretation of the datetime instance unless without that +attribute two (or no) interpretations are possible. Since it would be very confusing to have something called ``isdst`` that does not have the same semantics as ``tm_isdst``, we need a different name. Moreover, the ``datetime.datetime`` class already has -a method called ``dst()`` and if we called ``first`` "isdst", we would -necessarily have situations when "isdst" and ``bool(dst())`` values -are different. +a method called ``dst()`` and if we called ``fold`` "isdst", we would +necessarily have situations when "isdst" is zero but ``dst()`` is not +or the other way around. +Why "fold"? +----------- -Why "first"? ------------- +Suggested by Guido van Rossum and favored by one (but initially +disfavored by another) author. A consensus was reached after the +allowed values for the attribute were changed from False/True to 0/1. +The noun "fold" has correct connotations and easy mnemonic rules, but +at the same time does not invite unbased assumptions. -This is a working name chosen initially because the obvious -alternative ("second") conflicts with the existing attribute. It has -since become clear that it is desirable to have a flag with the -default value ``False`` and such that chronological ordering of -disambiguated (datetime, flag) pairs would match their lexicographical -order. -The following alternative names have been proposed: +What is "first"? +---------------- - **fold** - Suggested by Guido van Rossum and favored by one (but disfavored by another) author. Has - correct connotations and easy mnemonic rules, but at the same - time does not invite unbased assumptions. - +This was a working name of the attribute chosen initially because the +obvious alternative ("second") conflicts with the existing attribute. +It was rejected mostly on the grounds that it would make True a +default value. + +The following alternative names have also been considered: + **later** A close contender to "fold". One author dislikes it because it is confusable with equally fitting "latter," but in the age @@ -510,7 +532,7 @@ ---------------------- Several reasons have been raised to allow a ``None`` or -1 value for -the ``first`` flag: backward compatibility, analogy with ``tm_isdst`` +the ``fold`` attribute: backward compatibility, analogy with ``tm_isdst`` and strict checking for invalid times. @@ -518,23 +540,23 @@ ...................... It has been suggested that backward compatibility can be improved if -the default value of the ``first`` flag was ``None`` which would +the default value of the ``fold`` flag was ``None`` which would signal that pre-PEP behavior is requested. Based on the analysis -below, we believe that the proposed changes with the ``first=True`` +below, we believe that the proposed changes with the ``fold=0`` default are sufficiently backward compatible. This PEP provides only three ways for a program to discover that two otherwise identical datetime instances have different values of -``first``: (1) an explicit check of the ``first`` attribute; (2) if +``fold``: (1) an explicit check of the ``fold`` attribute; (2) if the instances are naive - conversion to another timezone using the ``astimezone()`` method; and (3) conversion to ``float`` using the ``timestamp()`` method. -Since ``first`` is a new attribute, the first option is not available +Since ``fold`` is a new attribute, the first option is not available to the existing programs. Note that option (2) only works for naive datetimes that happen to be in a fold or a gap in the system time -zone. In all other cases, the value of ``first`` will be ignored in -the conversion unless the instances use a ``first``-aware ``tzinfo`` +zone. In all other cases, the value of ``fold`` will be ignored in +the conversion unless the instances use a ``fold``-aware ``tzinfo`` which would not be available in a pre-PEP program. Similarly, the ``astimezone()`` called on a naive instance will not be available in such program because ``astimezone()`` does not currently work with @@ -548,7 +570,7 @@ ``mktime`` implementation, the programs can see different results or errors in those cases. With this PEP in place, the value of timestamp will be well-defined in those cases but will depend on the value of -the ``first`` flag. We consider the change in +the ``fold`` flag. We consider the change in ``datetime.timestamp()`` method behavior a bug fix enabled by this PEP. The old behavior can still be emulated by the users who depend on it by writing ``time.mktime(dt.timetuple()) + 1e-6*dt.microsecond`` @@ -563,16 +585,16 @@ determine whether DST is in effect for the given time from the rest of the fields) is the only choice that is useful in practice. -With the ``first`` flag, however, ``datetime.timestamp()`` will return +With the ``fold`` flag, however, ``datetime.timestamp()`` will return the same value as ``mktime`` with ``tm_isdst=-1`` in 99.98% of the time for most time zones with DST transitions. Moreover, ``tm_isdst=-1``-like behavior is specified *regardless* of the value -of ``first``. +of ``fold``. It is only in the 0.02% cases (2 hours per year) that the ``datetime.timestamp()`` and ``mktime`` with ``tm_isdst=-1`` may disagree. However, even in this case, most of the ``mktime`` -implementations will return the ``first=True`` or the ``first=False`` +implementations will return the ``fold=0`` or the ``fold=1`` value even though relevant standards allow ``mktime`` to return -1 and set an error code in those cases. @@ -602,22 +624,22 @@ >>> datetime.datetime.fromtimestamp(t) datetime.datetime(2015, 6, 1, 12, 0) -This PEP extends the same guarantee to both values of ``first``: +This PEP extends the same guarantee to both values of ``fold``: .. code:: - >>> t = datetime.datetime(2015, 6, 1, 12, first=True).timestamp() + >>> t = datetime.datetime(2015, 6, 1, 12, fold=0).timestamp() >>> datetime.datetime.fromtimestamp(t) datetime.datetime(2015, 6, 1, 12, 0) .. code:: - >>> t = datetime.datetime(2015, 6, 1, 12, first=False).timestamp() + >>> t = datetime.datetime(2015, 6, 1, 12, fold=1).timestamp() >>> datetime.datetime.fromtimestamp(t) datetime.datetime(2015, 6, 1, 12, 0) -Thus one of the suggested uses for ``first=-1`` -- to match the legacy -behavior -- is not needed. Either choice of ``first`` will match the +Thus one of the suggested uses for ``fold=-1`` -- to match the legacy +behavior -- is not needed. Either choice of ``fold`` will match the old behavior except in the few cases where the old behavior was undefined. @@ -625,7 +647,7 @@ Strict Invalid Time Checking ............................ -Another suggestion was to use ``first=-1`` or ``first=None`` to +Another suggestion was to use ``fold=-1`` or ``fold=None`` to indicate that the program truly has no means to deal with the folds and gaps and ``dt.utcoffset()`` should raise an error whenever ``dt`` represents an ambiguous or missing local time. @@ -642,10 +664,10 @@ def utcoffset(dt, raise_on_gap=True, raise_on_fold=False): u = dt.utcoffset() - v = dt.replace(first=not dt.first).utcoffset() + v = dt.replace(fold=not dt.fold).utcoffset() if u == v: return u - if (u < v) == dt.first: + if (u < v) == dt.fold: if raise_on_fold: raise AmbiguousTimeError else: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 05:15:06 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:15:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Nzgy?= =?utf-8?q?=3A_In_Idle_extension_config_dialog=2C_replace_tabs_with_sorted?= =?utf-8?q?_list=2E?= Message-ID: <20150827031505.29366.60228@psf.io> https://hg.python.org/cpython/rev/ce13593e378c changeset: 97518:ce13593e378c branch: 3.4 parent: 97487:54a9c649281d user: Terry Jan Reedy date: Wed Aug 26 23:13:22 2015 -0400 summary: Issue #24782: In Idle extension config dialog, replace tabs with sorted list. Patch by Mark Roseman. files: Lib/idlelib/configDialog.py | 81 ++++++++++++++---------- 1 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -1201,9 +1201,6 @@ # update the scrollbars to match the size of the inner frame size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) - if interior.winfo_reqwidth() != canvas.winfo_width(): - # update the canvas's width to fit the inner frame - canvas.config(width=interior.winfo_reqwidth()) interior.bind('', _configure_interior) def _configure_canvas(event): @@ -1323,38 +1320,56 @@ def create_widgets(self): """Create the dialog's widgets.""" + self.extension_names = StringVar(self) self.rowconfigure(0, weight=1) - self.rowconfigure(1, weight=0) - self.columnconfigure(0, weight=1) + self.columnconfigure(2, weight=1) + self.extension_list = Listbox(self, listvariable=self.extension_names, + selectmode='browse') + self.extension_list.bind('<>', self.extension_selected) + scroll = Scrollbar(self, command=self.extension_list.yview) + self.extension_list.yscrollcommand=scroll.set + self.details_frame = LabelFrame(self, width=250, height=250) + self.extension_list.grid(column=0, row=0, sticky='nws') + scroll.grid(column=1, row=0, sticky='ns') + self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) + self.configure(padx=10, pady=10) + self.config_frame = {} + self.current_extension = None - # create the tabbed pages - self.tabbed_page_set = TabbedPageSet( - self, page_names=self.extensions.keys(), - n_rows=None, max_tabs_per_row=5, - page_class=TabbedPageSet.PageRemove) - self.tabbed_page_set.grid(row=0, column=0, sticky=NSEW) - for ext_name in self.extensions: - self.create_tab_page(ext_name) + self.outerframe = self # TEMPORARY + self.tabbed_page_set = self.extension_list # TEMPORARY - self.create_action_buttons().grid(row=1) + # create the individual pages + ext_names = '' + for ext_name in sorted(self.extensions): + self.create_extension_frame(ext_name) + ext_names = ext_names + '{' + ext_name + '} ' + self.extension_names.set(ext_names) + self.extension_list.selection_set(0) + self.extension_selected(None) + self.create_action_buttons().grid(row=1, columnspan=3) + + def extension_selected(self, event): + newsel = self.extension_list.curselection() + if newsel: + newsel = self.extension_list.get(newsel) + if newsel is None or newsel != self.current_extension: + if self.current_extension: + self.details_frame.config(text='') + self.config_frame[self.current_extension].grid_forget() + self.current_extension = None + if newsel: + self.details_frame.config(text=newsel) + self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') + self.current_extension = newsel create_action_buttons = ConfigDialog.create_action_buttons - def create_tab_page(self, ext_name): - """Create the page for an extension.""" - - page = LabelFrame(self.tabbed_page_set.pages[ext_name].frame, - border=2, padx=2, relief=GROOVE, - text=' %s ' % ext_name) - page.pack(fill=BOTH, expand=True, padx=12, pady=2) - - # create the scrollable frame which will contain the entries - scrolled_frame = VerticalScrolledFrame(page, pady=2, height=250) - scrolled_frame.pack(side=BOTTOM, fill=BOTH, expand=TRUE) - entry_area = scrolled_frame.interior - entry_area.columnconfigure(0, weight=0) - entry_area.columnconfigure(1, weight=1) - + def create_extension_frame(self, ext_name): + """Create a frame holding the widgets to configure one extension""" + f = VerticalScrolledFrame(self.details_frame, height=250, width=250) + self.config_frame[ext_name] = f + entry_area = f.interior # create an entry for each configuration option for row, opt in enumerate(self.extensions[ext_name]): # create a row with a label and entry/checkbutton @@ -1365,15 +1380,15 @@ Checkbutton(entry_area, textvariable=var, variable=var, onvalue='True', offvalue='False', indicatoron=FALSE, selectcolor='', width=8 - ).grid(row=row, column=1, sticky=W, padx=7) + ).grid(row=row, column=1, sticky=W, padx=7) elif opt['type'] == 'int': Entry(entry_area, textvariable=var, validate='key', - validatecommand=(self.is_int, '%P') - ).grid(row=row, column=1, sticky=NSEW, padx=7) + validatecommand=(self.is_int, '%P') + ).grid(row=row, column=1, sticky=NSEW, padx=7) else: Entry(entry_area, textvariable=var - ).grid(row=row, column=1, sticky=NSEW, padx=7) + ).grid(row=row, column=1, sticky=NSEW, padx=7) return -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:15:06 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:15:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150827031506.76209.78321@psf.io> https://hg.python.org/cpython/rev/4141984cf362 changeset: 97519:4141984cf362 branch: 3.5 parent: 97514:9f7f6f7145f4 parent: 97518:ce13593e378c user: Terry Jan Reedy date: Wed Aug 26 23:13:43 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/configDialog.py | 81 ++++++++++++++---------- 1 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -1201,9 +1201,6 @@ # update the scrollbars to match the size of the inner frame size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) - if interior.winfo_reqwidth() != canvas.winfo_width(): - # update the canvas's width to fit the inner frame - canvas.config(width=interior.winfo_reqwidth()) interior.bind('', _configure_interior) def _configure_canvas(event): @@ -1323,38 +1320,56 @@ def create_widgets(self): """Create the dialog's widgets.""" + self.extension_names = StringVar(self) self.rowconfigure(0, weight=1) - self.rowconfigure(1, weight=0) - self.columnconfigure(0, weight=1) + self.columnconfigure(2, weight=1) + self.extension_list = Listbox(self, listvariable=self.extension_names, + selectmode='browse') + self.extension_list.bind('<>', self.extension_selected) + scroll = Scrollbar(self, command=self.extension_list.yview) + self.extension_list.yscrollcommand=scroll.set + self.details_frame = LabelFrame(self, width=250, height=250) + self.extension_list.grid(column=0, row=0, sticky='nws') + scroll.grid(column=1, row=0, sticky='ns') + self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) + self.configure(padx=10, pady=10) + self.config_frame = {} + self.current_extension = None - # create the tabbed pages - self.tabbed_page_set = TabbedPageSet( - self, page_names=self.extensions.keys(), - n_rows=None, max_tabs_per_row=5, - page_class=TabbedPageSet.PageRemove) - self.tabbed_page_set.grid(row=0, column=0, sticky=NSEW) - for ext_name in self.extensions: - self.create_tab_page(ext_name) + self.outerframe = self # TEMPORARY + self.tabbed_page_set = self.extension_list # TEMPORARY - self.create_action_buttons().grid(row=1) + # create the individual pages + ext_names = '' + for ext_name in sorted(self.extensions): + self.create_extension_frame(ext_name) + ext_names = ext_names + '{' + ext_name + '} ' + self.extension_names.set(ext_names) + self.extension_list.selection_set(0) + self.extension_selected(None) + self.create_action_buttons().grid(row=1, columnspan=3) + + def extension_selected(self, event): + newsel = self.extension_list.curselection() + if newsel: + newsel = self.extension_list.get(newsel) + if newsel is None or newsel != self.current_extension: + if self.current_extension: + self.details_frame.config(text='') + self.config_frame[self.current_extension].grid_forget() + self.current_extension = None + if newsel: + self.details_frame.config(text=newsel) + self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') + self.current_extension = newsel create_action_buttons = ConfigDialog.create_action_buttons - def create_tab_page(self, ext_name): - """Create the page for an extension.""" - - page = LabelFrame(self.tabbed_page_set.pages[ext_name].frame, - border=2, padx=2, relief=GROOVE, - text=' %s ' % ext_name) - page.pack(fill=BOTH, expand=True, padx=12, pady=2) - - # create the scrollable frame which will contain the entries - scrolled_frame = VerticalScrolledFrame(page, pady=2, height=250) - scrolled_frame.pack(side=BOTTOM, fill=BOTH, expand=TRUE) - entry_area = scrolled_frame.interior - entry_area.columnconfigure(0, weight=0) - entry_area.columnconfigure(1, weight=1) - + def create_extension_frame(self, ext_name): + """Create a frame holding the widgets to configure one extension""" + f = VerticalScrolledFrame(self.details_frame, height=250, width=250) + self.config_frame[ext_name] = f + entry_area = f.interior # create an entry for each configuration option for row, opt in enumerate(self.extensions[ext_name]): # create a row with a label and entry/checkbutton @@ -1365,15 +1380,15 @@ Checkbutton(entry_area, textvariable=var, variable=var, onvalue='True', offvalue='False', indicatoron=FALSE, selectcolor='', width=8 - ).grid(row=row, column=1, sticky=W, padx=7) + ).grid(row=row, column=1, sticky=W, padx=7) elif opt['type'] == 'int': Entry(entry_area, textvariable=var, validate='key', - validatecommand=(self.is_int, '%P') - ).grid(row=row, column=1, sticky=NSEW, padx=7) + validatecommand=(self.is_int, '%P') + ).grid(row=row, column=1, sticky=NSEW, padx=7) else: Entry(entry_area, textvariable=var - ).grid(row=row, column=1, sticky=NSEW, padx=7) + ).grid(row=row, column=1, sticky=NSEW, padx=7) return -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:15:06 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:15:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Nzgy?= =?utf-8?q?=3A_In_Idle_extension_config_dialog=2C_replace_tabs_with_sorted?= =?utf-8?q?_list=2E?= Message-ID: <20150827031505.67820.44980@psf.io> https://hg.python.org/cpython/rev/919cee158a89 changeset: 97517:919cee158a89 branch: 2.7 parent: 97484:da483bda6efc user: Terry Jan Reedy date: Wed Aug 26 23:13:16 2015 -0400 summary: Issue #24782: In Idle extension config dialog, replace tabs with sorted list. Patch by Mark Roseman. files: Lib/idlelib/configDialog.py | 81 ++++++++++++++---------- 1 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -1218,9 +1218,6 @@ # update the scrollbars to match the size of the inner frame size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) - if interior.winfo_reqwidth() != canvas.winfo_width(): - # update the canvas's width to fit the inner frame - canvas.config(width=interior.winfo_reqwidth()) interior.bind('', _configure_interior) def _configure_canvas(event): @@ -1340,38 +1337,56 @@ def create_widgets(self): """Create the dialog's widgets.""" + self.extension_names = StringVar(self) self.rowconfigure(0, weight=1) - self.rowconfigure(1, weight=0) - self.columnconfigure(0, weight=1) + self.columnconfigure(2, weight=1) + self.extension_list = Listbox(self, listvariable=self.extension_names, + selectmode='browse') + self.extension_list.bind('<>', self.extension_selected) + scroll = Scrollbar(self, command=self.extension_list.yview) + self.extension_list.yscrollcommand=scroll.set + self.details_frame = LabelFrame(self, width=250, height=250) + self.extension_list.grid(column=0, row=0, sticky='nws') + scroll.grid(column=1, row=0, sticky='ns') + self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) + self.configure(padx=10, pady=10) + self.config_frame = {} + self.current_extension = None - # create the tabbed pages - self.tabbed_page_set = TabbedPageSet( - self, page_names=self.extensions.keys(), - n_rows=None, max_tabs_per_row=5, - page_class=TabbedPageSet.PageRemove) - self.tabbed_page_set.grid(row=0, column=0, sticky=NSEW) - for ext_name in self.extensions: - self.create_tab_page(ext_name) + self.outerframe = self # TEMPORARY + self.tabbed_page_set = self.extension_list # TEMPORARY - self.create_action_buttons().grid(row=1) + # create the individual pages + ext_names = '' + for ext_name in sorted(self.extensions): + self.create_extension_frame(ext_name) + ext_names = ext_names + '{' + ext_name + '} ' + self.extension_names.set(ext_names) + self.extension_list.selection_set(0) + self.extension_selected(None) + self.create_action_buttons().grid(row=1, columnspan=3) + + def extension_selected(self, event): + newsel = self.extension_list.curselection() + if newsel: + newsel = self.extension_list.get(newsel) + if newsel is None or newsel != self.current_extension: + if self.current_extension: + self.details_frame.config(text='') + self.config_frame[self.current_extension].grid_forget() + self.current_extension = None + if newsel: + self.details_frame.config(text=newsel) + self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') + self.current_extension = newsel create_action_buttons = ConfigDialog.create_action_buttons.im_func - def create_tab_page(self, ext_name): - """Create the page for an extension.""" - - page = LabelFrame(self.tabbed_page_set.pages[ext_name].frame, - border=2, padx=2, relief=GROOVE, - text=' %s ' % ext_name) - page.pack(fill=BOTH, expand=True, padx=12, pady=2) - - # create the scrollable frame which will contain the entries - scrolled_frame = VerticalScrolledFrame(page, pady=2, height=250) - scrolled_frame.pack(side=BOTTOM, fill=BOTH, expand=TRUE) - entry_area = scrolled_frame.interior - entry_area.columnconfigure(0, weight=0) - entry_area.columnconfigure(1, weight=1) - + def create_extension_frame(self, ext_name): + """Create a frame holding the widgets to configure one extension""" + f = VerticalScrolledFrame(self.details_frame, height=250, width=250) + self.config_frame[ext_name] = f + entry_area = f.interior # create an entry for each configuration option for row, opt in enumerate(self.extensions[ext_name]): # create a row with a label and entry/checkbutton @@ -1382,15 +1397,15 @@ Checkbutton(entry_area, textvariable=var, variable=var, onvalue='True', offvalue='False', indicatoron=FALSE, selectcolor='', width=8 - ).grid(row=row, column=1, sticky=W, padx=7) + ).grid(row=row, column=1, sticky=W, padx=7) elif opt['type'] == 'int': Entry(entry_area, textvariable=var, validate='key', - validatecommand=(self.is_int, '%P') - ).grid(row=row, column=1, sticky=NSEW, padx=7) + validatecommand=(self.is_int, '%P') + ).grid(row=row, column=1, sticky=NSEW, padx=7) else: Entry(entry_area, textvariable=var - ).grid(row=row, column=1, sticky=NSEW, padx=7) + ).grid(row=row, column=1, sticky=NSEW, padx=7) return -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:15:07 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:15:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150827031506.29057.56728@psf.io> https://hg.python.org/cpython/rev/669f10ed5080 changeset: 97520:669f10ed5080 parent: 97516:1f94fec31265 parent: 97519:4141984cf362 user: Terry Jan Reedy date: Wed Aug 26 23:14:26 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/configDialog.py | 81 ++++++++++++++---------- 1 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -1201,9 +1201,6 @@ # update the scrollbars to match the size of the inner frame size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) - if interior.winfo_reqwidth() != canvas.winfo_width(): - # update the canvas's width to fit the inner frame - canvas.config(width=interior.winfo_reqwidth()) interior.bind('', _configure_interior) def _configure_canvas(event): @@ -1323,38 +1320,56 @@ def create_widgets(self): """Create the dialog's widgets.""" + self.extension_names = StringVar(self) self.rowconfigure(0, weight=1) - self.rowconfigure(1, weight=0) - self.columnconfigure(0, weight=1) + self.columnconfigure(2, weight=1) + self.extension_list = Listbox(self, listvariable=self.extension_names, + selectmode='browse') + self.extension_list.bind('<>', self.extension_selected) + scroll = Scrollbar(self, command=self.extension_list.yview) + self.extension_list.yscrollcommand=scroll.set + self.details_frame = LabelFrame(self, width=250, height=250) + self.extension_list.grid(column=0, row=0, sticky='nws') + scroll.grid(column=1, row=0, sticky='ns') + self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) + self.configure(padx=10, pady=10) + self.config_frame = {} + self.current_extension = None - # create the tabbed pages - self.tabbed_page_set = TabbedPageSet( - self, page_names=self.extensions.keys(), - n_rows=None, max_tabs_per_row=5, - page_class=TabbedPageSet.PageRemove) - self.tabbed_page_set.grid(row=0, column=0, sticky=NSEW) - for ext_name in self.extensions: - self.create_tab_page(ext_name) + self.outerframe = self # TEMPORARY + self.tabbed_page_set = self.extension_list # TEMPORARY - self.create_action_buttons().grid(row=1) + # create the individual pages + ext_names = '' + for ext_name in sorted(self.extensions): + self.create_extension_frame(ext_name) + ext_names = ext_names + '{' + ext_name + '} ' + self.extension_names.set(ext_names) + self.extension_list.selection_set(0) + self.extension_selected(None) + self.create_action_buttons().grid(row=1, columnspan=3) + + def extension_selected(self, event): + newsel = self.extension_list.curselection() + if newsel: + newsel = self.extension_list.get(newsel) + if newsel is None or newsel != self.current_extension: + if self.current_extension: + self.details_frame.config(text='') + self.config_frame[self.current_extension].grid_forget() + self.current_extension = None + if newsel: + self.details_frame.config(text=newsel) + self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') + self.current_extension = newsel create_action_buttons = ConfigDialog.create_action_buttons - def create_tab_page(self, ext_name): - """Create the page for an extension.""" - - page = LabelFrame(self.tabbed_page_set.pages[ext_name].frame, - border=2, padx=2, relief=GROOVE, - text=' %s ' % ext_name) - page.pack(fill=BOTH, expand=True, padx=12, pady=2) - - # create the scrollable frame which will contain the entries - scrolled_frame = VerticalScrolledFrame(page, pady=2, height=250) - scrolled_frame.pack(side=BOTTOM, fill=BOTH, expand=TRUE) - entry_area = scrolled_frame.interior - entry_area.columnconfigure(0, weight=0) - entry_area.columnconfigure(1, weight=1) - + def create_extension_frame(self, ext_name): + """Create a frame holding the widgets to configure one extension""" + f = VerticalScrolledFrame(self.details_frame, height=250, width=250) + self.config_frame[ext_name] = f + entry_area = f.interior # create an entry for each configuration option for row, opt in enumerate(self.extensions[ext_name]): # create a row with a label and entry/checkbutton @@ -1365,15 +1380,15 @@ Checkbutton(entry_area, textvariable=var, variable=var, onvalue='True', offvalue='False', indicatoron=FALSE, selectcolor='', width=8 - ).grid(row=row, column=1, sticky=W, padx=7) + ).grid(row=row, column=1, sticky=W, padx=7) elif opt['type'] == 'int': Entry(entry_area, textvariable=var, validate='key', - validatecommand=(self.is_int, '%P') - ).grid(row=row, column=1, sticky=NSEW, padx=7) + validatecommand=(self.is_int, '%P') + ).grid(row=row, column=1, sticky=NSEW, padx=7) else: Entry(entry_area, textvariable=var - ).grid(row=row, column=1, sticky=NSEW, padx=7) + ).grid(row=row, column=1, sticky=NSEW, padx=7) return -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:38:25 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:38:25 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Nzkw?= =?utf-8?q?=3A_Restore_unused_function=2E?= Message-ID: <20150827033825.79921.62122@psf.io> https://hg.python.org/cpython/rev/14ac7deba91f changeset: 97521:14ac7deba91f branch: 2.7 parent: 97517:919cee158a89 user: Terry Jan Reedy date: Wed Aug 26 23:37:09 2015 -0400 summary: Issue #24790: Restore unused function. files: Lib/idlelib/StackViewer.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,6 +120,9 @@ sublist.append(item) return sublist + def keys(self): # unused, left for possible 3rd parcy use + return self.object.keys() + def _stack_viewer(parent): # htest # root = tk.Tk() root.title("Test StackViewer") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:38:25 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:38:25 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Nzkw?= =?utf-8?q?=3A_Restore_unused_function=2E?= Message-ID: <20150827033825.22318.41730@psf.io> https://hg.python.org/cpython/rev/eec5e81b38d1 changeset: 97522:eec5e81b38d1 branch: 3.4 parent: 97518:ce13593e378c user: Terry Jan Reedy date: Wed Aug 26 23:37:14 2015 -0400 summary: Issue #24790: Restore unused function. files: Lib/idlelib/StackViewer.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,6 +120,9 @@ sublist.append(item) return sublist + def keys(self): # unused, left for possible 3rd parcy use + return list(self.object.keys()) + def _stack_viewer(parent): root = tk.Tk() root.title("Test StackViewer") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:38:28 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:38:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150827033826.19632.54107@psf.io> https://hg.python.org/cpython/rev/a150c7158ff2 changeset: 97524:a150c7158ff2 parent: 97520:669f10ed5080 parent: 97523:9db2a3139255 user: Terry Jan Reedy date: Wed Aug 26 23:37:47 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/StackViewer.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,6 +120,9 @@ sublist.append(item) return sublist + def keys(self): # unused, left for possible 3rd parcy use + return list(self.object.keys()) + def _stack_viewer(parent): root = tk.Tk() root.title("Test StackViewer") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 05:38:28 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 03:38:28 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150827033825.29069.11582@psf.io> https://hg.python.org/cpython/rev/9db2a3139255 changeset: 97523:9db2a3139255 branch: 3.5 parent: 97519:4141984cf362 parent: 97522:eec5e81b38d1 user: Terry Jan Reedy date: Wed Aug 26 23:37:31 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/StackViewer.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,6 +120,9 @@ sublist.append(item) return sublist + def keys(self): # unused, left for possible 3rd parcy use + return list(self.object.keys()) + def _stack_viewer(parent): root = tk.Tk() root.title("Test StackViewer") -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Thu Aug 27 09:57:51 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Thu, 27 Aug 2015 07:57:51 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-27 Message-ID: <078AA0FFE8C7034097F90205717F504611D75D36@IRSMSX102.ger.corp.intel.com> Results for project python_default-nightly, build date 2015-08-27 09:01:58 commit: a150c7158ff2edbaf8e68a6f535edc7520449cdd revision date: 2015-08-27 06:37:47 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Note: Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 -------------------------------------------------------------------------------- benchmark unit RSD* change since change since last run v3.4.3 -------------------------------------------------------------------------------- :-) django_v2 sec 0.27510% -0.32312% 7.11491% :-( pybench sec 0.22219% 0.15993% -2.19278% :-( regex_v8 sec 2.96840% 0.48701% -2.96437% :-| nbody sec 0.37896% 0.28862% -0.93200% :-| json_dump_v2 sec 0.30290% -0.46680% -1.10308% :-| normal_startup sec 0.72021% 0.01366% 0.04386% * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From python-checkins at python.org Thu Aug 27 14:40:43 2015 From: python-checkins at python.org (donald.stufft) Date: Thu, 27 Aug 2015 12:40:43 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Reword_the_call_to_action_in_?= =?utf-8?q?the_data_sovereignty_section?= Message-ID: <20150827124042.12125.34450@psf.io> https://hg.python.org/peps/rev/6c8a8f29a798 changeset: 5996:6c8a8f29a798 user: Donald Stufft date: Thu Aug 27 08:40:40 2015 -0400 summary: Reword the call to action in the data sovereignty section files: pep-0470.txt | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -300,11 +300,10 @@ solution for the problem of data sovereignty has been deferred and is considered outside of the scope for this PEP. -If someone for whom the issue of data sovereignty matters to them wishes to -put forth the effort, then at that time a system can be designed, implemented, -and ultimately deployed and operated that would satisfy both the needs of non -US users that cannot upload their projects to a system on US soil and the -quality of user experience that is attempted to be created on PyPI. +The data sovereignty issue will need to be addressed by someone with an +understanding of the restrictions and constraints involved. As the author of +this PEP does not have that expertise, it should be addressed in a separate +PEP. Rejected Proposals -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 16:19:52 2015 From: python-checkins at python.org (eric.smith) Date: Thu, 27 Aug 2015 14:19:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_a_note_that_the_str=2Ef?= =?utf-8?q?ormat=28=29_parser_is_not_suitable_for_use_when?= Message-ID: <20150827141952.22326.1497@psf.io> https://hg.python.org/peps/rev/a3faab8fb10a changeset: 5997:a3faab8fb10a user: Eric V. Smith date: Thu Aug 27 10:20:59 2015 -0400 summary: Added a note that the str.format() parser is not suitable for use when implementing f-strings. files: pep-0498.txt | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -470,6 +470,15 @@ >>> f'a={d[a]}' 'a=20' +Furthermore, the limited expressions that str.format() understands +need not be valid Python expressions. For example:: + + >>> '{i[";]}'.format(i={'";':4}) + '4' + +For this reason, the str.format() "expression parser" is not suitable +for use when implementing f-strings. + See [#]_ for a further discussion. It was this observation that led to full Python expressions being supported in f-strings. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 16:47:29 2015 From: python-checkins at python.org (eric.smith) Date: Thu, 27 Aug 2015 14:47:29 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_call_to_super=28=29=2E?= =?utf-8?b?X19uZXdfXy4=?= Message-ID: <20150827144715.29061.41851@psf.io> https://hg.python.org/peps/rev/c71667eea7f4 changeset: 5998:c71667eea7f4 user: Eric V. Smith date: Thu Aug 27 10:48:24 2015 -0400 summary: Fixed call to super().__new__. files: pep-0501.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -166,7 +166,7 @@ __slots__ = ("raw_template", "parsed_fields", "field_values") def __new__(cls, raw_template, parsed_fields, field_values): - self = super().__new__() + self = super().__new__(cls) self.raw_template = raw_template self.parsed_fields = parsed_fields self.field_values = field_values -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Aug 27 19:03:36 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 17:03:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E5?= Message-ID: <20150827170336.27307.4223@psf.io> https://hg.python.org/cpython/rev/b0e3eef95d3e changeset: 97528:b0e3eef95d3e parent: 97524:a150c7158ff2 parent: 97527:8270cf851d04 user: Terry Jan Reedy date: Thu Aug 27 13:02:47 2015 -0400 summary: Merge with 3.5 files: Lib/idlelib/StackViewer.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,7 +120,7 @@ sublist.append(item) return sublist - def keys(self): # unused, left for possible 3rd parcy use + def keys(self): # unused, left for possible 3rd party use return list(self.object.keys()) def _stack_viewer(parent): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 19:03:36 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 17:03:36 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Merge_with_3=2E4?= Message-ID: <20150827170336.22334.14548@psf.io> https://hg.python.org/cpython/rev/8270cf851d04 changeset: 97527:8270cf851d04 branch: 3.5 parent: 97523:9db2a3139255 parent: 97526:213ae5626493 user: Terry Jan Reedy date: Thu Aug 27 13:02:27 2015 -0400 summary: Merge with 3.4 files: Lib/idlelib/StackViewer.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,7 +120,7 @@ sublist.append(item) return sublist - def keys(self): # unused, left for possible 3rd parcy use + def keys(self): # unused, left for possible 3rd party use return list(self.object.keys()) def _stack_viewer(parent): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 19:04:11 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 17:04:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0Nzkw?= =?utf-8?q?=3A_correct_typo_noticed_by_Eric_Smith?= Message-ID: <20150827170336.79927.16663@psf.io> https://hg.python.org/cpython/rev/213ae5626493 changeset: 97526:213ae5626493 branch: 3.4 parent: 97522:eec5e81b38d1 user: Terry Jan Reedy date: Thu Aug 27 13:02:11 2015 -0400 summary: Issue #24790: correct typo noticed by Eric Smith files: Lib/idlelib/StackViewer.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,7 +120,7 @@ sublist.append(item) return sublist - def keys(self): # unused, left for possible 3rd parcy use + def keys(self): # unused, left for possible 3rd party use return list(self.object.keys()) def _stack_viewer(parent): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 19:04:11 2015 From: python-checkins at python.org (terry.reedy) Date: Thu, 27 Aug 2015 17:04:11 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0Nzkw?= =?utf-8?q?=3A_correct_typo_noticed_by_Eric_Smith?= Message-ID: <20150827170336.29067.18885@psf.io> https://hg.python.org/cpython/rev/514f5d610175 changeset: 97525:514f5d610175 branch: 2.7 parent: 97521:14ac7deba91f user: Terry Jan Reedy date: Thu Aug 27 13:01:45 2015 -0400 summary: Issue #24790: correct typo noticed by Eric Smith files: Lib/idlelib/StackViewer.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/StackViewer.py b/Lib/idlelib/StackViewer.py --- a/Lib/idlelib/StackViewer.py +++ b/Lib/idlelib/StackViewer.py @@ -120,7 +120,7 @@ sublist.append(item) return sublist - def keys(self): # unused, left for possible 3rd parcy use + def keys(self): # unused, left for possible 3rd party use return self.object.keys() def _stack_viewer(parent): # htest # -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 22:56:24 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 27 Aug 2015 20:56:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2324947=3A_Merge_with_3=2E5?= Message-ID: <20150827205615.19648.47152@psf.io> https://hg.python.org/cpython/rev/b76346142b49 changeset: 97531:b76346142b49 parent: 97528:b0e3eef95d3e parent: 97530:563d6f9fecfe user: Zachary Ware date: Thu Aug 27 15:55:48 2015 -0500 summary: Closes #24947: Merge with 3.5 files: Doc/library/asyncio-eventloop.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -6,7 +6,7 @@ =============== The event loop is the central execution device provided by :mod:`asyncio`. -It provides multiple facilities, amongst which: +It provides multiple facilities, including: * Registering, executing and cancelling delayed calls (timeouts). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 22:56:24 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 27 Aug 2015 20:56:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0OTQ3?= =?utf-8?q?=3A_Fix_grammar_in_asyncio_doc?= Message-ID: <20150827205614.29063.6393@psf.io> https://hg.python.org/cpython/rev/cf15066861fc changeset: 97529:cf15066861fc branch: 3.4 parent: 97526:213ae5626493 user: Zachary Ware date: Thu Aug 27 15:54:39 2015 -0500 summary: Issue #24947: Fix grammar in asyncio doc Patch by tagatac files: Doc/library/asyncio-eventloop.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -6,7 +6,7 @@ =============== The event loop is the central execution device provided by :mod:`asyncio`. -It provides multiple facilities, amongst which: +It provides multiple facilities, including: * Registering, executing and cancelling delayed calls (timeouts). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Aug 27 22:56:24 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 27 Aug 2015 20:56:24 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324947=3A_Merge_3=2E4?= Message-ID: <20150827205615.19634.1084@psf.io> https://hg.python.org/cpython/rev/563d6f9fecfe changeset: 97530:563d6f9fecfe branch: 3.5 parent: 97527:8270cf851d04 parent: 97529:cf15066861fc user: Zachary Ware date: Thu Aug 27 15:55:24 2015 -0500 summary: Issue #24947: Merge 3.4 files: Doc/library/asyncio-eventloop.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -6,7 +6,7 @@ =============== The event loop is the central execution device provided by :mod:`asyncio`. -It provides multiple facilities, amongst which: +It provides multiple facilities, including: * Registering, executing and cancelling delayed calls (timeouts). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 28 00:36:33 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 27 Aug 2015 22:36:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxMTEy?= =?utf-8?q?=3A_Fix_regression_in_unittest=2EexpectedFailure_on_subclasses?= =?utf-8?q?=2E?= Message-ID: <20150827223633.27321.75397@psf.io> https://hg.python.org/cpython/rev/a90c6d608b85 changeset: 97532:a90c6d608b85 branch: 3.4 parent: 97529:cf15066861fc user: Robert Collins date: Fri Aug 28 10:34:51 2015 +1200 summary: Issue #21112: Fix regression in unittest.expectedFailure on subclasses. Patch from Berker Peksag. files: Lib/unittest/case.py | 7 ++- Lib/unittest/test/test_skipping.py | 33 ++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -563,8 +563,11 @@ finally: result.stopTest(self) return - expecting_failure = getattr(testMethod, - "__unittest_expecting_failure__", False) + expecting_failure_method = getattr(testMethod, + "__unittest_expecting_failure__", False) + expecting_failure_class = getattr(self, + "__unittest_expecting_failure__", False) + expecting_failure = expecting_failure_class or expecting_failure_method outcome = _Outcome(result) try: self._outcome = outcome diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -120,6 +120,39 @@ self.assertEqual(result.expectedFailures[0][0], test) self.assertTrue(result.wasSuccessful()) + def test_expected_failure_with_wrapped_class(self): + @unittest.expectedFailure + class Foo(unittest.TestCase): + def test_1(self): + self.assertTrue(False) + + events = [] + result = LoggingResult(events) + test = Foo("test_1") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expectedFailures[0][0], test) + self.assertTrue(result.wasSuccessful()) + + def test_expected_failure_with_wrapped_subclass(self): + class Foo(unittest.TestCase): + def test_1(self): + self.assertTrue(False) + + @unittest.expectedFailure + class Bar(Foo): + pass + + events = [] + result = LoggingResult(events) + test = Bar("test_1") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expectedFailures[0][0], test) + self.assertTrue(result.wasSuccessful()) + def test_expected_failure_subtests(self): # A failure in any subtest counts as the expected failure of the # whole test. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -75,6 +75,9 @@ Library ------- +- Issue #21112: Fix regression in unittest.expectedFailure on subclasses. + Patch from Berker Peksag. + - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 28 00:36:37 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 27 Aug 2015 22:36:37 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2321112=3A_Fix_regression_in_unittest=2EexpectedFailure?= =?utf-8?q?_on_subclasses=2E?= Message-ID: <20150827223633.19654.35546@psf.io> https://hg.python.org/cpython/rev/ac3f1a6b1de2 changeset: 97533:ac3f1a6b1de2 branch: 3.5 parent: 97530:563d6f9fecfe parent: 97532:a90c6d608b85 user: Robert Collins date: Fri Aug 28 10:35:14 2015 +1200 summary: Issue #21112: Fix regression in unittest.expectedFailure on subclasses. Patch from Berker Peksag. files: Lib/unittest/case.py | 7 ++- Lib/unittest/test/test_skipping.py | 33 ++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -583,8 +583,11 @@ finally: result.stopTest(self) return - expecting_failure = getattr(testMethod, - "__unittest_expecting_failure__", False) + expecting_failure_method = getattr(testMethod, + "__unittest_expecting_failure__", False) + expecting_failure_class = getattr(self, + "__unittest_expecting_failure__", False) + expecting_failure = expecting_failure_class or expecting_failure_method outcome = _Outcome(result) try: self._outcome = outcome diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -120,6 +120,39 @@ self.assertEqual(result.expectedFailures[0][0], test) self.assertTrue(result.wasSuccessful()) + def test_expected_failure_with_wrapped_class(self): + @unittest.expectedFailure + class Foo(unittest.TestCase): + def test_1(self): + self.assertTrue(False) + + events = [] + result = LoggingResult(events) + test = Foo("test_1") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expectedFailures[0][0], test) + self.assertTrue(result.wasSuccessful()) + + def test_expected_failure_with_wrapped_subclass(self): + class Foo(unittest.TestCase): + def test_1(self): + self.assertTrue(False) + + @unittest.expectedFailure + class Bar(Foo): + pass + + events = [] + result = LoggingResult(events) + test = Bar("test_1") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expectedFailures[0][0], test) + self.assertTrue(result.wasSuccessful()) + def test_expected_failure_subtests(self): # A failure in any subtest counts as the expected failure of the # whole test. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,6 +14,9 @@ Library ------- +- Issue #21112: Fix regression in unittest.expectedFailure on subclasses. + Patch from Berker Peksag. + - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 28 00:36:38 2015 From: python-checkins at python.org (robert.collins) Date: Thu, 27 Aug 2015 22:36:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321112=3A_Fix_regression_in_unittest=2EexpectedF?= =?utf-8?q?ailure_on_subclasses=2E?= Message-ID: <20150827223638.27321.99234@psf.io> https://hg.python.org/cpython/rev/bf789ae9bde7 changeset: 97534:bf789ae9bde7 parent: 97531:b76346142b49 parent: 97533:ac3f1a6b1de2 user: Robert Collins date: Fri Aug 28 10:36:01 2015 +1200 summary: Issue #21112: Fix regression in unittest.expectedFailure on subclasses. Patch from Berker Peksag. files: Lib/unittest/case.py | 7 ++- Lib/unittest/test/test_skipping.py | 33 ++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -583,8 +583,11 @@ finally: result.stopTest(self) return - expecting_failure = getattr(testMethod, - "__unittest_expecting_failure__", False) + expecting_failure_method = getattr(testMethod, + "__unittest_expecting_failure__", False) + expecting_failure_class = getattr(self, + "__unittest_expecting_failure__", False) + expecting_failure = expecting_failure_class or expecting_failure_method outcome = _Outcome(result) try: self._outcome = outcome diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -120,6 +120,39 @@ self.assertEqual(result.expectedFailures[0][0], test) self.assertTrue(result.wasSuccessful()) + def test_expected_failure_with_wrapped_class(self): + @unittest.expectedFailure + class Foo(unittest.TestCase): + def test_1(self): + self.assertTrue(False) + + events = [] + result = LoggingResult(events) + test = Foo("test_1") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expectedFailures[0][0], test) + self.assertTrue(result.wasSuccessful()) + + def test_expected_failure_with_wrapped_subclass(self): + class Foo(unittest.TestCase): + def test_1(self): + self.assertTrue(False) + + @unittest.expectedFailure + class Bar(Foo): + pass + + events = [] + result = LoggingResult(events) + test = Bar("test_1") + test.run(result) + self.assertEqual(events, + ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertEqual(result.expectedFailures[0][0], test) + self.assertTrue(result.wasSuccessful()) + def test_expected_failure_subtests(self): # A failure in any subtest counts as the expected failure of the # whole test. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -79,6 +79,9 @@ Library ------- +- Issue #21112: Fix regression in unittest.expectedFailure on subclasses. + Patch from Berker Peksag. + - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Fri Aug 28 15:30:12 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Fri, 28 Aug 2015 13:30:12 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-28 Message-ID: <078AA0FFE8C7034097F90205717F504611D768DD@IRSMSX102.ger.corp.intel.com> Results for project python_default-nightly, build date 2015-08-28 15:14:59 commit: bf789ae9bde7ea45d67bc43bf7c0f7bf2d30a4e3 revision date: 2015-08-28 01:36:01 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 ------------------------------------------------------------------------------------------ benchmark RSD* change since change since current rev with last run v3.4.3 regrtest PGO ------------------------------------------------------------------------------------------ :-) django_v2 0.16722% -0.00619% 8.44470% 18.34905% :-( pybench 0.15008% -0.14507% -2.48972% 9.37152% :-( regex_v8 2.82708% -0.24967% -2.96286% 4.15702% :-| nbody 0.12185% -0.10869% -0.85104% 9.95802% :-( json_dump_v2 0.37986% -1.66504% -2.83949% 13.81661% :-| normal_startup 0.97518% -0.20145% -0.70811% 5.42905% ------------------------------------------------------------------------------------------ Note: Benchmark results are measured in seconds. * - Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From python-checkins at python.org Fri Aug 28 17:03:03 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 15:03:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Escape_some_backslashes=2E?= Message-ID: <20150828150302.22326.40575@psf.io> https://hg.python.org/peps/rev/bd32f6184572 changeset: 5999:bd32f6184572 user: Eric V. Smith date: Fri Aug 28 11:03:07 2015 -0400 summary: Escape some backslashes. files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -403,7 +403,7 @@ of uses of string.Template, but hundreds of uses of str.format(). Another proposed alternative was to have the substituted text between -\{ and } or between \{ and \}. While this syntax would probably be +\\{ and } or between \\{ and \\}. While this syntax would probably be desirable if all string literals were to support interpolation, this PEP only supports strings that are already marked with the leading 'f'. As such, the PEP is using unadorned braces to denoted substituted -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 17:16:18 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 15:16:18 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_section_on_order_of_eva?= =?utf-8?q?luation=2E?= Message-ID: <20150828151617.21439.25039@psf.io> https://hg.python.org/peps/rev/548cbfbd3d8f changeset: 6000:548cbfbd3d8f user: Eric V. Smith date: Fri Aug 28 11:16:23 2015 -0400 summary: Added section on order of evaluation. files: pep-0498.txt | 20 +++++++++++++++++--- 1 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -602,10 +602,24 @@ f'{x:.{width}}' -Expressions with side effects ------------------------------ +Evaluation order of expressions +------------------------------- -xxx +The expressions in an f-string are evaluated in left-to-right +order. This is detectable only if the expressions have side effects:: + + >>> def fn(l, incr): + ... result = l[0] + ... l[0] += incr + ... return result + ... + >>> lst = [0] + >>> f'{fn(lst,2)} {fn(lst,3)}' + '0 2' + >>> f'{fn(lst,2)} {fn(lst,3)}' + '5 7' + >>> lst + [10] Expressions used multiple times ------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 17:43:36 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 15:43:36 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Moved_a_sentence_to_where_it_?= =?utf-8?q?makes_more_sense=2E?= Message-ID: <20150828154152.19654.45686@psf.io> https://hg.python.org/peps/rev/abefd4edf039 changeset: 6001:abefd4edf039 user: Eric V. Smith date: Fri Aug 28 11:41:58 2015 -0400 summary: Moved a sentence to where it makes more sense. files: pep-0498.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -470,6 +470,9 @@ >>> f'a={d[a]}' 'a=20' +See [#]_ for a further discussion. It was this observation that led to +full Python expressions being supported in f-strings. + Furthermore, the limited expressions that str.format() understands need not be valid Python expressions. For example:: @@ -479,9 +482,6 @@ For this reason, the str.format() "expression parser" is not suitable for use when implementing f-strings. -See [#]_ for a further discussion. It was this observation that led to -full Python expressions being supported in f-strings. - Triple-quoted f-strings ----------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 18:21:48 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 16:21:48 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Moved_order_of_evaluation_int?= =?utf-8?q?o_the_Specification_section=2C_since_it=27s_guaranteed=2E?= Message-ID: <20150828162058.29071.57789@psf.io> https://hg.python.org/peps/rev/220f74d3b747 changeset: 6002:220f74d3b747 user: Eric V. Smith date: Fri Aug 28 12:21:04 2015 -0400 summary: Moved order of evaluation into the Specification section, since it's guaranteed. files: pep-0498.txt | 38 +++++++++++++++++++------------------- 1 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -360,6 +360,25 @@ For ease of readability, leading and trailing whitespace in expressions is ignored. +Evaluation order of expressions +------------------------------- + +The expressions in an f-string are evaluated in left-to-right +order. This is detectable only if the expressions have side effects:: + + >>> def fn(l, incr): + ... result = l[0] + ... l[0] += incr + ... return result + ... + >>> lst = [0] + >>> f'{fn(lst,2)} {fn(lst,3)}' + '0 2' + >>> f'{fn(lst,2)} {fn(lst,3)}' + '5 7' + >>> lst + [10] + Discussion ========== @@ -602,25 +621,6 @@ f'{x:.{width}}' -Evaluation order of expressions -------------------------------- - -The expressions in an f-string are evaluated in left-to-right -order. This is detectable only if the expressions have side effects:: - - >>> def fn(l, incr): - ... result = l[0] - ... l[0] += incr - ... return result - ... - >>> lst = [0] - >>> f'{fn(lst,2)} {fn(lst,3)}' - '0 2' - >>> f'{fn(lst,2)} {fn(lst,3)}' - '5 7' - >>> lst - [10] - Expressions used multiple times ------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 20:26:54 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 18:26:54 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_specification_for_order?= =?utf-8?q?_of_escape_sequence_processing=2E?= Message-ID: <20150828182653.21441.87706@psf.io> https://hg.python.org/peps/rev/c008f6cc1411 changeset: 6003:c008f6cc1411 user: Eric V. Smith date: Fri Aug 28 14:26:58 2015 -0400 summary: Added specification for order of escape sequence processing. files: pep-0498.txt | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -208,6 +208,25 @@ brackets, or braces. The exception is that the '!=' operator is special cased. +Escape sequences +---------------- + +Scanning an f-string for expressions happens after escape sequences +are decode. Because hex(ord('{')) == 0x7b, that means that the +f-string f'\u007b4*10}' is decoded to f'{4*10}', which evaluates as +the integer 40:: + + >>> f'\u007b4*10}' + '40' + >>> f'\x7b4*10}' + '40' + >>> f'\x7b4*10\N{RIGHT CURLY BRACKET}' + '40' + +These examples aren't generally useful, they're just to show that +escape sequences are processed before f-strings are parsed for +expressions. + Code equivalence ---------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 20:27:52 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 18:27:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_awkward_wording=2E?= Message-ID: <20150828182751.12115.13737@psf.io> https://hg.python.org/peps/rev/a941c4b200d5 changeset: 6004:a941c4b200d5 user: Eric V. Smith date: Fri Aug 28 14:27:58 2015 -0400 summary: Fixed awkward wording. files: pep-0498.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -212,9 +212,9 @@ ---------------- Scanning an f-string for expressions happens after escape sequences -are decode. Because hex(ord('{')) == 0x7b, that means that the -f-string f'\u007b4*10}' is decoded to f'{4*10}', which evaluates as -the integer 40:: +are decoded. Because hex(ord('{')) == 0x7b, the f-string +f'\u007b4*10}' is decoded to f'{4*10}', which evaluates as the integer +40:: >>> f'\u007b4*10}' '40' -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 20:53:51 2015 From: python-checkins at python.org (brett.cannon) Date: Fri, 28 Aug 2015 18:53:51 +0000 Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Issue_324934=3A_Skip_dj?= =?utf-8?q?ango=5Fv2_under_Python_3=2E6_due_to_a_use_of?= Message-ID: <20150828185340.79915.207@psf.io> https://hg.python.org/benchmarks/rev/2f3b3c6c1190 changeset: 221:2f3b3c6c1190 user: Brett Cannon date: Fri Aug 28 11:53:36 2015 -0700 summary: Issue 324934: Skip django_v2 under Python 3.6 due to a use of inspect.getargspec. Thanks to Florin Papa from Intel for reporting the bug. files: perf.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -1446,7 +1446,7 @@ bm_env = {"PYTHONPATH": django_path} return MeasureGeneric(python, options, bm_path, bm_env) - at VersionRange() + at VersionRange(None, '3.5') def BM_Django_v2(*args, **kwargs): return SimpleBenchmark(MeasureDjangoV2, *args, **kwargs) -- Repository URL: https://hg.python.org/benchmarks From python-checkins at python.org Fri Aug 28 20:58:58 2015 From: python-checkins at python.org (eric.smith) Date: Fri, 28 Aug 2015 18:58:58 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_escape_sequence=2E?= Message-ID: <20150828185858.21445.92667@psf.io> https://hg.python.org/peps/rev/bf851048278c changeset: 6005:bf851048278c user: Eric V. Smith date: Fri Aug 28 14:59:05 2015 -0400 summary: Fixed escape sequence. files: pep-0498.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -213,7 +213,7 @@ Scanning an f-string for expressions happens after escape sequences are decoded. Because hex(ord('{')) == 0x7b, the f-string -f'\u007b4*10}' is decoded to f'{4*10}', which evaluates as the integer +f'\\u007b4*10}' is decoded to f'{4*10}', which evaluates as the integer 40:: >>> f'\u007b4*10}' -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Aug 28 21:20:51 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 28 Aug 2015 19:20:51 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0ODgx?= =?utf-8?q?=3A_Fixed_setting_binary_mode_in_Python_implementation_of_FileI?= =?utf-8?q?O?= Message-ID: <20150828192050.29354.67806@psf.io> https://hg.python.org/cpython/rev/687da8760a58 changeset: 97535:687da8760a58 branch: 3.5 parent: 97533:ac3f1a6b1de2 user: Serhiy Storchaka date: Fri Aug 28 22:17:04 2015 +0300 summary: Issue #24881: Fixed setting binary mode in Python implementation of FileIO on Windows and Cygwin. Patch from Akira Li. files: Lib/_pyio.py | 3 ++- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -8,12 +8,13 @@ import errno import array import stat +import sys # Import _thread instead of threading to reduce startup cost try: from _thread import allocate_lock as Lock except ImportError: from _dummy_thread import allocate_lock as Lock -if os.name == 'win32': +if sys.platform in {'win32', 'cygwin'}: from msvcrt import setmode as _setmode else: _setmode = None diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,6 +14,9 @@ Library ------- +- Issue #24881: Fixed setting binary mode in Python implementation of FileIO + on Windows and Cygwin. Patch from Akira Li. + - Issue #21112: Fix regression in unittest.expectedFailure on subclasses. Patch from Berker Peksag. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 28 21:21:30 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 28 Aug 2015 19:21:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324881=3A_Fixed_setting_binary_mode_in_Python_im?= =?utf-8?q?plementation_of_FileIO?= Message-ID: <20150828192051.79909.13406@psf.io> https://hg.python.org/cpython/rev/2dd9294f679d changeset: 97536:2dd9294f679d parent: 97534:bf789ae9bde7 parent: 97535:687da8760a58 user: Serhiy Storchaka date: Fri Aug 28 22:20:29 2015 +0300 summary: Issue #24881: Fixed setting binary mode in Python implementation of FileIO on Windows and Cygwin. Patch from Akira Li. files: Lib/_pyio.py | 3 ++- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -8,12 +8,13 @@ import errno import array import stat +import sys # Import _thread instead of threading to reduce startup cost try: from _thread import allocate_lock as Lock except ImportError: from _dummy_thread import allocate_lock as Lock -if os.name == 'win32': +if sys.platform in {'win32', 'cygwin'}: from msvcrt import setmode as _setmode else: _setmode = None diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -79,6 +79,9 @@ Library ------- +- Issue #24881: Fixed setting binary mode in Python implementation of FileIO + on Windows and Cygwin. Patch from Akira Li. + - Issue #21112: Fix regression in unittest.expectedFailure on subclasses. Patch from Berker Peksag. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Aug 28 22:56:57 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Fri, 28 Aug 2015 20:56:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_typos_in_TZ_format_d?= =?utf-8?q?escription?= Message-ID: <20150828205657.10955.94045@psf.io> https://hg.python.org/cpython/rev/d0ff55a6b02f changeset: 97537:d0ff55a6b02f user: Alexander Belopolsky date: Fri Aug 28 16:56:45 2015 -0400 summary: Fixed typos in TZ format description files: Doc/library/time.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -634,11 +634,11 @@ it is possible to refer to February 29. :samp:`M{m}.{n}.{d}` - The *d*'th day (0 <= *d* <= 6) or week *n* of month *m* of the year (1 + The *d*'th day (0 <= *d* <= 6) of week *n* of month *m* of the year (1 <= *n* <= 5, 1 <= *m* <= 12, where week 5 means "the last *d* day in month *m*" which may occur in either the fourth or the fifth week). Week 1 is the first week in which the *d*'th day occurs. Day - zero is Sunday. + zero is a Sunday. ``time`` has the same format as ``offset`` except that no leading sign ('-' or '+') is allowed. The default, if time is not given, is 02:00:00. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 29 03:45:15 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 29 Aug 2015 01:45:15 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_a_section_on_the_same_e?= =?utf-8?q?xpression_being_used_multiple_times_in_the_same?= Message-ID: <20150829014341.17298.16467@psf.io> https://hg.python.org/peps/rev/9af8765a7661 changeset: 6006:9af8765a7661 user: Eric V. Smith date: Fri Aug 28 21:43:48 2015 -0400 summary: Added a section on the same expression being used multiple times in the same f-string. files: pep-0498.txt | 41 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 38 insertions(+), 3 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -640,10 +640,45 @@ f'{x:.{width}}' -Expressions used multiple times -------------------------------- +The same expression used multiple times +--------------------------------------- -xxx +Every expression in braces in an f-string is evaluated exactly +once. If the same expression is used more than once in the same +f-string, it will be evaluated multiple times. However, it's undefined +which result will show up in the resulting string value. For purposes +of this section, two expressions are the same if they have the exact +same literal text defining them. For example, '{i}' and '{i}' are the +same expression, but '{i}' and '{ i}' are not, due to the extra space +in the second expression. + +For example, given:: + + >>> def fn(lst): + ... lst[0] += 1 + ... return lst[0] + ... + >>> lst=[0] + >>> f'{fn(lst)} {fn(lst)}' + '1 2' + +The resulting f-string might have the value '1 2', '2 2', '1 1', or +even '2 1'. + +However:: + + >>> lst=[0] + >>> f'{fn(lst)} { fn(lst)}' + '1 2' + +This f-string will always have the value '1 2'. This is due to the two +expressions not being the same: the space in the second example makes +the two expressions distinct. + +This restriction is in place in order to allow for a possible future +extension allowing translated strings, wherein the expression +substitutions would be identified by their text values as they show up +between the braces. References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 29 07:13:56 2015 From: python-checkins at python.org (zach.ware) Date: Sat, 29 Aug 2015 05:13:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0OTUz?= =?utf-8?q?=3A_Include_ICC_version_in_sys=2Eversion_string_when_bulit_with?= =?utf-8?q?_ICC_on?= Message-ID: <20150829051356.3663.99328@psf.io> https://hg.python.org/cpython/rev/ca88db01bb51 changeset: 97539:ca88db01bb51 branch: 3.5 parent: 97535:687da8760a58 user: Zachary Ware date: Fri Aug 28 23:52:31 2015 -0500 summary: Issue #24953: Include ICC version in sys.version string when bulit with ICC on Windows files: PC/pyconfig.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/PC/pyconfig.h b/PC/pyconfig.h --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -147,7 +147,11 @@ #define MS_WINI64 #define PYD_PLATFORM_TAG "win_ia64" #elif defined(_M_X64) || defined(_M_AMD64) +#if defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else #define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") +#endif /* __INTEL_COMPILER */ #define MS_WINX64 #define PYD_PLATFORM_TAG "win_amd64" #else @@ -194,7 +198,11 @@ #if defined(MS_WIN32) && !defined(MS_WIN64) #if defined(_M_IX86) +#if defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else #define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") +#endif /* __INTEL_COMPILER */ #define PYD_PLATFORM_TAG "win32" #elif defined(_M_ARM) #define COMPILER _Py_PASTE_VERSION("32 bit (ARM)") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 29 08:12:31 2015 From: python-checkins at python.org (zach.ware) Date: Sat, 29 Aug 2015 06:12:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2324953=3A_Merge_with_3=2E5?= Message-ID: <20150829051356.21287.85032@psf.io> https://hg.python.org/cpython/rev/1633fe209375 changeset: 97540:1633fe209375 parent: 97537:d0ff55a6b02f parent: 97539:ca88db01bb51 user: Zachary Ware date: Sat Aug 29 00:13:14 2015 -0500 summary: Closes #24953: Merge with 3.5 files: PC/pyconfig.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/PC/pyconfig.h b/PC/pyconfig.h --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -147,7 +147,11 @@ #define MS_WINI64 #define PYD_PLATFORM_TAG "win_ia64" #elif defined(_M_X64) || defined(_M_AMD64) +#if defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else #define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") +#endif /* __INTEL_COMPILER */ #define MS_WINX64 #define PYD_PLATFORM_TAG "win_amd64" #else @@ -194,7 +198,11 @@ #if defined(MS_WIN32) && !defined(MS_WIN64) #if defined(_M_IX86) +#if defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else #define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") +#endif /* __INTEL_COMPILER */ #define PYD_PLATFORM_TAG "win32" #elif defined(_M_ARM) #define COMPILER _Py_PASTE_VERSION("32 bit (ARM)") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 29 12:51:26 2015 From: python-checkins at python.org (zach.ware) Date: Sat, 29 Aug 2015 10:51:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0OTUz?= =?utf-8?q?=3A_Include_ICC_version_in_sys=2Eversion_string_when_bulit_with?= =?utf-8?q?_ICC_on?= Message-ID: <20150829051356.21257.15509@psf.io> https://hg.python.org/cpython/rev/3639520c3fe9 changeset: 97538:3639520c3fe9 branch: 2.7 parent: 97525:514f5d610175 user: Zachary Ware date: Fri Aug 28 23:52:31 2015 -0500 summary: Issue #24953: Include ICC version in sys.version string when bulit with ICC on Windows files: PC/pyconfig.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/PC/pyconfig.h b/PC/pyconfig.h --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -148,7 +148,11 @@ #define COMPILER _Py_PASTE_VERSION("64 bit (Itanium)") #define MS_WINI64 #elif defined(_M_X64) || defined(_M_AMD64) +#ifdef __INTEL_COMPILER +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else #define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") +#endif /* __INTEL_COMPILER */ #define MS_WINX64 #else #define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)") @@ -204,7 +208,11 @@ #if defined(MS_WIN32) && !defined(MS_WIN64) #ifdef _M_IX86 +#ifdef __INTEL_COMPILER +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else #define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") +#endif /* __INTEL_COMPILER */ #else #define COMPILER _Py_PASTE_VERSION("32 bit (Unknown)") #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Aug 29 17:05:55 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 15:05:55 +0000 Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_merge?= Message-ID: <20150829144037.26999.48248@psf.io> https://hg.python.org/peps/rev/036f89f3cea8 changeset: 6008:036f89f3cea8 parent: 6007:8cc94276db23 parent: 6006:9af8765a7661 user: Donald Stufft date: Sat Aug 29 10:40:35 2015 -0400 summary: merge files: pep-0498.txt | 91 ++++++++++++++++++++++++++++++++++++--- pep-0501.txt | 2 +- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -208,6 +208,25 @@ brackets, or braces. The exception is that the '!=' operator is special cased. +Escape sequences +---------------- + +Scanning an f-string for expressions happens after escape sequences +are decoded. Because hex(ord('{')) == 0x7b, the f-string +f'\\u007b4*10}' is decoded to f'{4*10}', which evaluates as the integer +40:: + + >>> f'\u007b4*10}' + '40' + >>> f'\x7b4*10}' + '40' + >>> f'\x7b4*10\N{RIGHT CURLY BRACKET}' + '40' + +These examples aren't generally useful, they're just to show that +escape sequences are processed before f-strings are parsed for +expressions. + Code equivalence ---------------- @@ -360,6 +379,25 @@ For ease of readability, leading and trailing whitespace in expressions is ignored. +Evaluation order of expressions +------------------------------- + +The expressions in an f-string are evaluated in left-to-right +order. This is detectable only if the expressions have side effects:: + + >>> def fn(l, incr): + ... result = l[0] + ... l[0] += incr + ... return result + ... + >>> lst = [0] + >>> f'{fn(lst,2)} {fn(lst,3)}' + '0 2' + >>> f'{fn(lst,2)} {fn(lst,3)}' + '5 7' + >>> lst + [10] + Discussion ========== @@ -403,7 +441,7 @@ of uses of string.Template, but hundreds of uses of str.format(). Another proposed alternative was to have the substituted text between -\{ and } or between \{ and \}. While this syntax would probably be +\\{ and } or between \\{ and \\}. While this syntax would probably be desirable if all string literals were to support interpolation, this PEP only supports strings that are already marked with the leading 'f'. As such, the PEP is using unadorned braces to denoted substituted @@ -473,6 +511,15 @@ See [#]_ for a further discussion. It was this observation that led to full Python expressions being supported in f-strings. +Furthermore, the limited expressions that str.format() understands +need not be valid Python expressions. For example:: + + >>> '{i[";]}'.format(i={'";':4}) + '4' + +For this reason, the str.format() "expression parser" is not suitable +for use when implementing f-strings. + Triple-quoted f-strings ----------------------- @@ -593,15 +640,45 @@ f'{x:.{width}}' -Expressions with side effects ------------------------------ +The same expression used multiple times +--------------------------------------- -xxx +Every expression in braces in an f-string is evaluated exactly +once. If the same expression is used more than once in the same +f-string, it will be evaluated multiple times. However, it's undefined +which result will show up in the resulting string value. For purposes +of this section, two expressions are the same if they have the exact +same literal text defining them. For example, '{i}' and '{i}' are the +same expression, but '{i}' and '{ i}' are not, due to the extra space +in the second expression. -Expressions used multiple times -------------------------------- +For example, given:: -xxx + >>> def fn(lst): + ... lst[0] += 1 + ... return lst[0] + ... + >>> lst=[0] + >>> f'{fn(lst)} {fn(lst)}' + '1 2' + +The resulting f-string might have the value '1 2', '2 2', '1 1', or +even '2 1'. + +However:: + + >>> lst=[0] + >>> f'{fn(lst)} { fn(lst)}' + '1 2' + +This f-string will always have the value '1 2'. This is due to the two +expressions not being the same: the space in the second example makes +the two expressions distinct. + +This restriction is in place in order to allow for a possible future +extension allowing translated strings, wherein the expression +substitutions would be identified by their text values as they show up +between the braces. References ========== diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -166,7 +166,7 @@ __slots__ = ("raw_template", "parsed_fields", "field_values") def __new__(cls, raw_template, parsed_fields, field_values): - self = super().__new__() + self = super().__new__(cls) self.raw_template = raw_template self.parsed_fields = parsed_fields self.field_values = field_values -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 29 17:06:28 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 15:06:28 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_Paul_Moore_as_Delegate=2C?= =?utf-8?q?_remove_Data_Sovereignty_section=2C_add_Opposition?= Message-ID: <20150829144037.21257.76542@psf.io> https://hg.python.org/peps/rev/8cc94276db23 changeset: 6007:8cc94276db23 parent: 5996:6c8a8f29a798 user: Donald Stufft date: Sat Aug 29 10:40:20 2015 -0400 summary: Add Paul Moore as Delegate, remove Data Sovereignty section, add Opposition section files: pep-0470.txt | 49 +++++++++++++++++++++++---------------- 1 files changed, 29 insertions(+), 20 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -2,8 +2,8 @@ Title: Removing External Hosting Support on PyPI Version: $Revision$ Last-Modified: $Date$ -Author: Donald Stufft , -BDFL-Delegate: TBD +Author: Donald Stufft +BDFL-Delegate: Paul Moore Discussions-To: distutils-sig at python.org Status: Draft Type: Process @@ -284,26 +284,35 @@ Remote Code Execution via a Man In The Middle attack. -Data Sovereignty -================ +Opposition +========== -In the discussions around previous versions of this PEP, one of the key use -cases for wanting to host files externally to PyPI was due to data sovereignty -requirements for people living in jurisdictions outside of the USA, where PyPI -is currently hosted. The author of this PEP is not blind to these concerns and -realizes that this PEP represents a regression for the people that have these -concerns, however the current situation is presenting an extremely poor user -experience and the feature is only being used by a small percentage of -projects. In addition, the data sovereignty problems requires familarity with -the laws outside of the home jurisdiction of the author of this PEP, who is -also the principal developer and operator of PyPI. For these reasons, a -solution for the problem of data sovereignty has been deferred and is -considered outside of the scope for this PEP. +The primary opposition to this PEP is that some people may want to not host on +PyPI for any number of reasons such as the PyPI Terms of Service or Data +Sovereignty requirements for a particular jurisdiction. For these people this +PEP represents a regression in the ability for end users to discover what +options are required to install their projects. -The data sovereignty issue will need to be addressed by someone with an -understanding of the restrictions and constraints involved. As the author of -this PEP does not have that expertise, it should be addressed in a separate -PEP. +The projects that are currently unwilling to host on PyPI can be split into +two general categories, those that would be willing to host on PyPI but for +some particular missing feature, and those that will never be willing to host +on PyPI for any reason. + +It is the opinion of this PEP that for those who will never be willing to host +on PyPI for any reason, that those projects should rely on the support of +multiple repositories that pip and setuptools already possess and which this +PEP recommends to all installers. These projects may still use PyPI as an index +for users to discover through the web interface and should document what +options are needed in order to install within the long description of their +projects, which is a freeform field which can structure the information however +is most useful for their particular project. This is a model which is battle +tested in virtually every Linux distribution. + +For the projects that would host on PyPI but for some particular missing +feature, it is the opinion of this PEP that instead of the legacy feature that +this PEP aims to remove, they would be be best served by identifying which +features are missing and then designing a good solution for those particular +issues. Rejected Proposals -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 29 22:02:16 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 29 Aug 2015 20:02:16 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Improve_some_wording=2E?= Message-ID: <20150829200209.21285.65187@psf.io> https://hg.python.org/peps/rev/1b81820a0131 changeset: 6009:1b81820a0131 user: Eric V. Smith date: Sat Aug 29 16:02:17 2015 -0400 summary: Improve some wording. files: pep-0498.txt | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -102,8 +102,8 @@ >>> f'The value is {value}.' 'The value is 80.' -f-strings provide a concise, readable way to include expressions -inside strings. +f-strings provide a concise, readable way to include the value of +Python expressions inside strings. In this sense, string.Template and %-formatting have similar shortcomings to str.format(), but also support fewer formatting @@ -643,9 +643,8 @@ The same expression used multiple times --------------------------------------- -Every expression in braces in an f-string is evaluated exactly -once. If the same expression is used more than once in the same -f-string, it will be evaluated multiple times. However, it's undefined +Every expression in braces in an f-string is evaluated exactly once +for each time it appears in the f-string. However, it's undefined which result will show up in the resulting string value. For purposes of this section, two expressions are the same if they have the exact same literal text defining them. For example, '{i}' and '{i}' are the -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 29 22:20:10 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 29 Aug 2015 20:20:10 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Added_inline_literal_markup?= =?utf-8?q?=2E?= Message-ID: <20150829202010.3647.26760@psf.io> https://hg.python.org/peps/rev/1b761906cca8 changeset: 6010:1b761906cca8 user: Eric V. Smith date: Sat Aug 29 16:20:18 2015 -0400 summary: Added inline literal markup. files: pep-0498.txt | 262 ++++++++++++++++++++------------------ 1 files changed, 135 insertions(+), 127 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -14,10 +14,10 @@ ======== Python supports multiple ways to format text strings. These include -%-formatting [#]_, str.format [#]_, and string.Template [#]_. Each of -these methods have their advantages, but in addition have -disadvantages that make them cumbersome to use in practice. This PEP -proposed to add a new string formatting mechanism: Literal String +%-formatting [#]_, ``str.format()`` [#]_, and ``string.Template`` +[#]_. Each of these methods have their advantages, but in addition +have disadvantages that make them cumbersome to use in practice. This +PEP proposed to add a new string formatting mechanism: Literal String Formatting. In this PEP, such strings will be refered to as "f-strings", taken from the leading character used to denote such strings. @@ -43,8 +43,8 @@ A similar feature was proposed in PEP 215 [#]_. PEP 215 proposed to support a subset of Python expressions, and did not support the -type-specific string formatting (the __format__ method) which was -introduced with PEP 3101 [#]_. +type-specific string formatting (the ``__format__()`` method) which +was introduced with PEP 3101 [#]_. Rationale ========= @@ -75,16 +75,16 @@ >>> 'error: %s' % (msg,) "error: ('disk failure', 32)" -str.format() was added to address some of these problems with +``str.format()`` was added to address some of these problems with %-formatting. In particular, it uses normal function call syntax (and therefor supports multiple parameters) and it is extensible through -the __format__() method on the object being converted to a string. See -PEP-3101 for a detailed rationale. This PEP reuses much of the -str.format() syntax and machinery, in order to provide continuity with -an existing Python string formatting mechanism. +the ``__format__()`` method on the object being converted to a +string. See PEP-3101 for a detailed rationale. This PEP reuses much of +the ``str.format()`` syntax and machinery, in order to provide +continuity with an existing Python string formatting mechanism. -However, str.format() is not without its issues. Chief among them is -its verbosity. For example, the text 'value' is repeated here:: +However, ``str.format()`` is not without its issues. Chief among them +is its verbosity. For example, the text ``value`` is repeated here:: >>> value = 4 * 20 >>> 'The value is {value}.'.format(value=value) @@ -105,20 +105,21 @@ f-strings provide a concise, readable way to include the value of Python expressions inside strings. -In this sense, string.Template and %-formatting have similar -shortcomings to str.format(), but also support fewer formatting -options. In particular, they do not support the __format__ protocol, -so that there is no way to control how a specific object is converted -to a string, nor can it be extended to additional types that want to -control how they are converted to strings (such as Decimal and -datetime). This example is not possible with string.Template:: +In this sense, ``string.Template`` and %-formatting have similar +shortcomings to ``str.format()``, but also support fewer formatting +options. In particular, they do not support the ``__format__`` +protocol, so that there is no way to control how a specific object is +converted to a string, nor can it be extended to additional types that +want to control how they are converted to strings (such as ``Decimal`` +and ``datetime``). This example is not possible with +``string.Template``:: >>> value = 1234 >>> f'input={value:#0.6x}' 'input=0x04d2' -And neither %-formatting nor string.Template can control formatting -such as:: +And neither %-formatting nor ``string.Template`` can control +formatting such as:: >>> date = datetime.date(1991, 10, 12) >>> f'{date} was on a {date:%A}' @@ -183,38 +184,38 @@ start of an expression. Following the expression, an optional type conversion may be -specified. The allowed conversions are '!s', '!r', or '!a'. These are -treated the same as in str.format: '!s' calls str() on the expression, -'!r' calls repr() on the expression, and '!a' calls ascii() on the -expression. These conversions are applied before the call to -__format__. The only reason to use '!s' is if you want to specify a -format specifier that applies to str, not to the type of the -expression. +specified. The allowed conversions are ``'!s'``, ``'!r'``, or +``'!a'``. These are treated the same as in ``str.format()``: ``'!s'`` +calls ``str()`` on the expression, ``'!r'`` calls ``repr()`` on the +expression, and ``'!a'`` calls ``ascii()`` on the expression. These +conversions are applied before the call to ``__format__``. The only +reason to use ``'!s'`` is if you want to specify a format specifier +that applies to ``str``, not to the type of the expression. -Similar to str.format, optional format specifiers maybe be included -inside the f-string, separated from the expression (or the type -conversion, if specified) by a colon. If a format specifier is not -provied, an empty string is used. +Similar to ``str.format()``, optional format specifiers maybe be +included inside the f-string, separated from the expression (or the +type conversion, if specified) by a colon. If a format specifier is +not provied, an empty string is used. So, an f-string looks like:: f ' { } text ... ' -The resulting expression's __format__ method is called with the format -specifier. The resulting value is used when building the value of the -f-string. +The resulting expression's ``__format__`` method is called with the +format specifier. The resulting value is used when building the value +of the f-string. -Expressions cannot contain ':' or '!' outside of strings or parens, -brackets, or braces. The exception is that the '!=' operator is -special cased. +Expressions cannot contain ``':'`` or ``'!'`` outside of strings or +parens, brackets, or braces. The exception is that the ``'!='`` +operator is allowed as a special case. Escape sequences ---------------- Scanning an f-string for expressions happens after escape sequences -are decoded. Because hex(ord('{')) == 0x7b, the f-string -f'\\u007b4*10}' is decoded to f'{4*10}', which evaluates as the integer -40:: +are decoded. Because ``hex(ord('{')) == 0x7b``, the f-string +``f'\\u007b4*10}'`` is decoded to ``f'{4*10}'``, which evaluates as +the integer 40:: >>> f'\u007b4*10}' '40' @@ -232,8 +233,8 @@ The exact code used to implement f-strings is not specified. However, it is guaranteed that any embedded value that is converted to a string -will use that value's __format__ method. This is the same mechanism -that str.format() uses to convert values to strings. +will use that value's ``__format__`` method. This is the same +mechanism that ``str.format()`` uses to convert values to strings. For example, this code:: @@ -269,9 +270,9 @@ 'result=20' After stripping leading and trailing whitespace (see below), the -expression is parsed with the equivalent of ast.parse(expression, -'', 'eval') [#]_. Note that this restricts the expression: it -cannot contain any newlines, for example:: +expression is parsed with the equivalent of ``ast.parse(expression, +'', 'eval')`` [#]_. Note that this restricts the expression: +it cannot contain any newlines, for example:: >>> x = 0 >>> f'''{x @@ -282,7 +283,7 @@ SyntaxError: invalid syntax But note that this works, since the newline is removed from the -string, and the spaces in front of the '1' are allowed in an +string, and the spaces in front of the ``'1'`` are allowed in an expression:: >>> f'{x+\ @@ -302,9 +303,9 @@ 'result: 12.35' Once expressions in a format specifier are evaluated (if necessary), -format specifiers are not interpreted by the f-string evaluator. Just as -in str.format(), they are merely passed in to the __format__() method -of the object being formatted. +format specifiers are not interpreted by the f-string evaluator. Just +as in ``str.format()``, they are merely passed in to the +``__format__()`` method of the object being formatted. Concatenating strings --------------------- @@ -332,7 +333,7 @@ Either compile time or run time errors can occur when processing f-strings. Compile time errors are limited to those errors that can be detected when scanning an f-string. These errors all raise -SyntaxError. +``SyntaxError``. Unmatched braces:: @@ -416,45 +417,48 @@ Because the compiler must be involved in evaluating the expressions contained in the interpolated strings, there must be some way to denote to the compiler which strings should be evaluated. This PEP -chose a leading 'f' character preceeding the string literal. This is -similar to how 'b' and 'r' prefixes change the meaning of the string -itself, at compile time. Other prefixes were suggested, such as 'i'. No -option seemed better than the other, so 'f' was chosen. +chose a leading ``'f'`` character preceeding the string literal. This +is similar to how ``'b'`` and ``'r'`` prefixes change the meaning of +the string itself, at compile time. Other prefixes were suggested, +such as ``'i'``. No option seemed better than the other, so ``'f'`` +was chosen. Another option was to support special functions, known to the -compiler, such as Format(). This seems like too much magic for Python: -not only is there a chance for collision with existing identifiers, -the PEP author feels that it's better to signify the magic with a -string prefix character. +compiler, such as ``Format()``. This seems like too much magic for +Python: not only is there a chance for collision with existing +identifiers, the PEP author feels that it's better to signify the +magic with a string prefix character. How to specify the location of expressions in f-strings ******************************************************* -This PEP supports the same syntax as str.format() for distinguishing -replacement text inside strings: expressions are contained inside -braces. There were other options suggested, such as string.Template's -$identifier or ${expression}. +This PEP supports the same syntax as ``str.format()`` for +distinguishing replacement text inside strings: expressions are +contained inside braces. There were other options suggested, such as +``string.Template``'s ``$identifier`` or ``${expression}``. -While $identifier is no doubt more familiar to shell scripters and -users of some other languages, in Python str.format() is heavily +While ``$identifier`` is no doubt more familiar to shell scripters and +users of some other languages, in Python ``str.format()`` is heavily used. A quick search of Python's standard library shows only a handful -of uses of string.Template, but hundreds of uses of str.format(). +of uses of ``string.Template``, but hundreds of uses of +``str.format()``. Another proposed alternative was to have the substituted text between -\\{ and } or between \\{ and \\}. While this syntax would probably be -desirable if all string literals were to support interpolation, this -PEP only supports strings that are already marked with the leading -'f'. As such, the PEP is using unadorned braces to denoted substituted -text, in order to leverage end user familiarity with str.format(). +``\\{`` and ``}`` or between ``\\{`` and ``\\}``. While this syntax +would probably be desirable if all string literals were to support +interpolation, this PEP only supports strings that are already marked +with the leading ``'f'``. As such, the PEP is using unadorned braces +to denoted substituted text, in order to leverage end user familiarity +with ``str.format()``. Supporting full Python expressions ********************************** Many people on the python-ideas discussion wanted support for either only single identifiers, or a limited subset of Python expressions -(such as the subset supported by str.format()). This PEP supports full -Python expressions inside the braces. Without full expressions, some -desirable usage would be cumbersome. For example:: +(such as the subset supported by ``str.format()``). This PEP supports +full Python expressions inside the braces. Without full expressions, +some desirable usage would be cumbersome. For example:: >>> f'Column={col_idx+1}' >>> f'number of items: {len(items)}' @@ -484,19 +488,20 @@ ------------------------------------------------------- There is one small difference between the limited expressions allowed -in str.format() and the full expressions allowed inside f-strings. The -difference is in how index lookups are performed. In str.format(), -index values that do not look like numbers are converted to strings:: +in ``str.format()`` and the full expressions allowed inside +f-strings. The difference is in how index lookups are performed. In +``str.format()``, index values that do not look like numbers are +converted to strings:: >>> d = {'a': 10, 'b': 20} >>> 'a={d[a]}'.format(d=d) 'a=10' -Notice that the index value is converted to the string "a" when it is -looked up in the dict. +Notice that the index value is converted to the string ``'a'`` when it +is looked up in the dict. However, in f-strings, you would need to use a literal for the value -of 'a':: +of ``'a'``:: >>> f'a={d["a"]}' 'a=10' @@ -511,7 +516,7 @@ See [#]_ for a further discussion. It was this observation that led to full Python expressions being supported in f-strings. -Furthermore, the limited expressions that str.format() understands +Furthermore, the limited expressions that ``str.format()`` understands need not be valid Python expressions. For example:: >>> '{i[";]}'.format(i={'";':4}) @@ -525,7 +530,7 @@ Triple quoted f-strings are allowed. These strings are parsed just as normal triple-quoted strings are. After parsing, the normal f-string -logic is applied, and __format__() on each value is called. +logic is applied, and ``__format__()`` on each value is called. Raw f-strings ------------- @@ -542,29 +547,30 @@ No binary f-strings ------------------- -For the same reason that we don't support bytes.format(), you may not -combine 'f' with 'b' string literals. The primary problem is that an -object's __format__() method may return Unicode data that is not -compatible with a bytes string. +For the same reason that we don't support ``bytes.format()``, you may +not combine ``'f'`` with ``'b'`` string literals. The primary problem +is that an object's ``__format__()`` method may return Unicode data that +is not compatible with a bytes string. Binary f-strings would first require a solution for -bytes.format(). This idea has been proposed in the past, most recently -in PEP 461 [#]_. The discussions of such a feature usually suggest either +``bytes.format()``. This idea has been proposed in the past, most +recently in PEP 461 [#]_. The discussions of such a feature usually +suggest either - - adding a method such as __bformat__() so an object can control how - it is converted to bytes, or + - adding a method such as ``__bformat__()`` so an object can control + how it is converted to bytes, or - - having bytes.format() not be as general purpose or extensible as - str.format(). + - having ``bytes.format()`` not be as general purpose or extensible + as ``str.format()``. Both of these remain as options in the future, if such functionality is desired. -!s, !r, and !a are redundant ----------------------------- +``!s``, ``!r``, and ``!a`` are redundant +---------------------------------------- -The !s, !r, and !a are not strictly required. Because arbitrary -expressions are allowed inside the f-strings, this code:: +The ``!s``, ``!r``, and ``!a`` are not strictly required. Because +arbitrary expressions are allowed inside the f-strings, this code:: >>> a = 'some string' >>> f'{a!r}' @@ -575,23 +581,23 @@ >>> f'{repr(a)}' "'some string'" -Similarly, !s can be replaced by calls to str() and !a by calls to -ascii(). +Similarly, ``!s`` can be replaced by calls to ``str()`` and ``!a`` by +calls to ``ascii()``. -However, !s, !r, and !a are supported by this PEP in order to minimize -the differences with str.format(). !s, !r, and !a are required in -str.format() because it does not allow the execution of arbitrary -expressions. +However, ``!s``, ``!r``, and ``!a`` are supported by this PEP in order +to minimize the differences with ``str.format()``. ``!s``, ``!r``, and +``!a`` are required in ``str.format()`` because it does not allow the +execution of arbitrary expressions. Lambdas inside expressions -------------------------- -Because lambdas use the ':' character, they cannot appear outside of -parenthesis in an expression. The colon is interpreted as the start of -the format specifier, which means the start of the lambda expression -is seen and is syntactically invalid. As there's no practical use for -a plain lambda in an f-string expression, this is not seen as much of -a limitation. +Because lambdas use the ``':'`` character, they cannot appear outside +of parenthesis in an expression. The colon is interpreted as the start +of the format specifier, which means the start of the lambda +expression is seen and is syntactically invalid. As there's no +practical use for a plain lambda in an f-string expression, this is +not seen as much of a limitation. If you feel you must use lambdas, they may be used inside of parens:: @@ -602,27 +608,27 @@ ================================== Here are some examples from Python source code that currently use -str.format(), and how they would look with f-strings. This PEP does -not recommend wholesale converting to f-strings, these are just -examples of real-world usages of str.format() and how they'd look if -written from scratch using f-strings. +``str.format()``, and how they would look with f-strings. This PEP +does not recommend wholesale converting to f-strings, these are just +examples of real-world usages of ``str.format()`` and how they'd look +if written from scratch using f-strings. -Lib/asyncio/locks.py:: +``Lib/asyncio/locks.py``:: extra = '{},waiters:{}'.format(extra, len(self._waiters)) extra = f'{extra},waiters:{len(self._waiters)}' -Lib/configparser.py:: +``Lib/configparser.py``:: message.append(" [line {0:2d}]".format(lineno)) message.append(f" [line {lineno:2d}]") -Tools/clinic/clinic.py:: +``Tools/clinic/clinic.py``:: methoddef_name = "{}_METHODDEF".format(c_basename.upper()) methoddef_name = f"{c_basename.upper()}_METHODDEF" -python-config.py:: +``python-config.py``:: print("Usage: {0} [{1}]".format(sys.argv[0], '|'.join('--'+opt for opt in valid_opts)), file=sys.stderr) print(f"Usage: {sys.argv[0]} [{'|'.join('--'+opt for opt in valid_opts)}]", file=sys.stderr) @@ -645,11 +651,13 @@ Every expression in braces in an f-string is evaluated exactly once for each time it appears in the f-string. However, it's undefined -which result will show up in the resulting string value. For purposes -of this section, two expressions are the same if they have the exact -same literal text defining them. For example, '{i}' and '{i}' are the -same expression, but '{i}' and '{ i}' are not, due to the extra space -in the second expression. +which result will show up in the resulting string value. This only +matters for expressions with side effects. + +For purposes of this section, two expressions are the same if they +have the exact same literal text defining them. For example, ``'{i}'`` +and ``'{i}'`` are the same expression, but ``'{i}'`` and ``'{i }'`` +are not, due to the extra space in the second expression. For example, given:: @@ -661,8 +669,8 @@ >>> f'{fn(lst)} {fn(lst)}' '1 2' -The resulting f-string might have the value '1 2', '2 2', '1 1', or -even '2 1'. +The resulting f-string might have the value ``'1 2'``, ``'2 2'``, +``'1 1'``, or even ``'2 1'``. However:: @@ -670,9 +678,9 @@ >>> f'{fn(lst)} { fn(lst)}' '1 2' -This f-string will always have the value '1 2'. This is due to the two -expressions not being the same: the space in the second example makes -the two expressions distinct. +This f-string will always have the value ``'1 2'``. This is due to the +two expressions not being the same: the space in the second example +makes the two expressions distinct. This restriction is in place in order to allow for a possible future extension allowing translated strings, wherein the expression -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 29 22:20:55 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 29 Aug 2015 20:20:55 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fixed_wording=2E?= Message-ID: <20150829202055.17318.21783@psf.io> https://hg.python.org/peps/rev/233a90f64c88 changeset: 6011:233a90f64c88 user: Eric V. Smith date: Sat Aug 29 16:21:04 2015 -0400 summary: Fixed wording. files: pep-0498.txt | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -569,8 +569,9 @@ ``!s``, ``!r``, and ``!a`` are redundant ---------------------------------------- -The ``!s``, ``!r``, and ``!a`` are not strictly required. Because -arbitrary expressions are allowed inside the f-strings, this code:: +The ``!s``, ``!r``, and ``!a`` conversions are not strictly +required. Because arbitrary expressions are allowed inside the +f-strings, this code:: >>> a = 'some string' >>> f'{a!r}' -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Aug 29 23:45:29 2015 From: python-checkins at python.org (eric.smith) Date: Sat, 29 Aug 2015 21:45:29 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Yet_another_attempt_to_clear_?= =?utf-8?q?up_wording_in_this_section=2E?= Message-ID: <20150829214529.117774.4076@psf.io> https://hg.python.org/peps/rev/0b996faa2381 changeset: 6012:0b996faa2381 user: Eric V. Smith date: Sat Aug 29 17:45:36 2015 -0400 summary: Yet another attempt to clear up wording in this section. files: pep-0498.txt | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -650,10 +650,11 @@ The same expression used multiple times --------------------------------------- -Every expression in braces in an f-string is evaluated exactly once -for each time it appears in the f-string. However, it's undefined -which result will show up in the resulting string value. This only -matters for expressions with side effects. +Every expression in an f-string is evaluated exactly once for each +time it appears in the f-string. However, when the same expression +appears more than once in an f-string, it's undefined which result +will be used in the resulting string value. This only matters for +expressions with side effects. For purposes of this section, two expressions are the same if they have the exact same literal text defining them. For example, ``'{i}'`` @@ -685,8 +686,8 @@ This restriction is in place in order to allow for a possible future extension allowing translated strings, wherein the expression -substitutions would be identified by their text values as they show up -between the braces. +substitutions would be identified by their text representations in the +f-strings. References ========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 00:00:37 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 22:00:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Update_setupto?= =?utf-8?q?ols_to_18=2E2_and_pip_to_7=2E1=2E2?= Message-ID: <20150829220037.26521.26926@psf.io> https://hg.python.org/cpython/rev/dcfe871b56ac changeset: 97541:dcfe871b56ac branch: 3.5 parent: 97506:d64c1c22d1f7 user: Donald Stufft date: Sat Aug 29 13:57:46 2015 -0400 summary: Update setuptools to 18.2 and pip to 7.1.2 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "18.0.1" +_SETUPTOOLS_VERSION = "18.2" -_PIP_VERSION = "7.1.0" +_PIP_VERSION = "7.1.2" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.0-py2.py3-none-any.whl deleted file mode 100644 index 76fcad1c7efb6223b049967e84fda31f9fd68dfc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-7.1.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e490155f0ca7f4ddb64c93c39fb2efb8795cd08 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.0.1-py2.py3-none-any.whl deleted file mode 100644 index 67aaca50a921a164fac7d721bc2aa80735c5515e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-18.2-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4288d68e074466894d8a2342e113737df7b7649 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 00:00:42 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 22:00:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy41IC0+IDMuNSk6?= =?utf-8?q?_Null_Merge_from_3=2E5=2E0_to_3=2E5=2E1?= Message-ID: <20150829220038.82581.69102@psf.io> https://hg.python.org/cpython/rev/81222106eabe changeset: 97542:81222106eabe branch: 3.5 parent: 97539:ca88db01bb51 parent: 97541:dcfe871b56ac user: Donald Stufft date: Sat Aug 29 18:00:26 2015 -0400 summary: Null Merge from 3.5.0 to 3.5.1 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 00:01:18 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 22:01:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Null_Merge_from_3=2E5_to_default?= Message-ID: <20150829220117.82505.28939@psf.io> https://hg.python.org/cpython/rev/7996fa5f503f changeset: 97543:7996fa5f503f parent: 97540:1633fe209375 parent: 97542:81222106eabe user: Donald Stufft date: Sat Aug 29 18:01:01 2015 -0400 summary: Null Merge from 3.5 to default files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 01:11:00 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 23:11:00 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_470_to_flesh_out_P?= =?utf-8?q?aul=27s_suggestions?= Message-ID: <20150829231058.82614.25593@psf.io> https://hg.python.org/peps/rev/8ddbde2dfd45 changeset: 6013:8ddbde2dfd45 user: Donald Stufft date: Sat Aug 29 19:10:55 2015 -0400 summary: Update PEP 470 to flesh out Paul's suggestions files: pep-0470.txt | 99 ++++++++++++++++++++++++++++----------- 1 files changed, 70 insertions(+), 29 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -196,6 +196,13 @@ repository. The exact specifics of how that is achieved is up to each individual implementation. +The `Python packaging guide `_ MUST be updated +with a section detailing the options for setting up their own repository so +that any project that wishes to not host on PyPI in the future can reference +that documentation. This should include the suggestion that projects relying on +hosting their own repositories should document in their project description how +to install their project. + Deprecation and Removal of Link Spidering ========================================= @@ -225,7 +232,8 @@ on PyPI and **MUST** include links to a script or package that will enable them to enter their PyPI credentials and package name and have it automatically download and re-host all of their files on PyPI. This email **MUST** also -include instructions for setting up their own index page. This email must also contain a link to the Terms of Service for PyPI as many users may have signed +include instructions for setting up their own index page. This email must also +contain a link to the Terms of Service for PyPI as many users may have signed up a long time ago and may not recall what those terms are. Finally this email must also contain a list of the links registered with PyPI where we were able to detect an installable file was located. @@ -284,35 +292,67 @@ Remote Code Execution via a Man In The Middle attack. -Opposition -========== +Frequently Asked Questions +========================== -The primary opposition to this PEP is that some people may want to not host on -PyPI for any number of reasons such as the PyPI Terms of Service or Data -Sovereignty requirements for a particular jurisdiction. For these people this -PEP represents a regression in the ability for end users to discover what -options are required to install their projects. +I can't host my project on PyPI because of , what should I do? +----------------------------------------------------------------- -The projects that are currently unwilling to host on PyPI can be split into -two general categories, those that would be willing to host on PyPI but for -some particular missing feature, and those that will never be willing to host -on PyPI for any reason. +First you should decide if is something inherient to PyPI, or if PyPI could +grow a feature to solve for you. If PyPI can add a feature to enable you to +host your project on PyPI then you should propose that feature. However, if +is something inherient to PyPI, such as wanting to maintain control over your +own files, then you should setup your own package repository and instruct your +users in your project's description to add it to the list of repositories their +installer of choice will use. -It is the opinion of this PEP that for those who will never be willing to host -on PyPI for any reason, that those projects should rely on the support of -multiple repositories that pip and setuptools already possess and which this -PEP recommends to all installers. These projects may still use PyPI as an index -for users to discover through the web interface and should document what -options are needed in order to install within the long description of their -projects, which is a freeform field which can structure the information however -is most useful for their particular project. This is a model which is battle -tested in virtually every Linux distribution. -For the projects that would host on PyPI but for some particular missing -feature, it is the opinion of this PEP that instead of the legacy feature that -this PEP aims to remove, they would be be best served by identifying which -features are missing and then designing a good solution for those particular -issues. +My users have a worse experience with this PEP than before, how do I explain that? +---------------------------------------------------------------------------------- + +Part of this answer is going to be specific to each individual project, you'll +need to explain to your users what caused you to decide to host in your own +repository instead of utilizing one that they already have in their installer's +default list of repositories. However, part of this answer will also be +explaining that the previous behavior of transparently including external links +was both a security hazard (given that in most cases it allowed a MITM to +execute arbitrary Python code on the end users machine) and a reliability +concern and that PEP 438 attempted to resolve this by making them explicitly +opt in, but that PEP 438 brought along with it a number of serious usability +issues. PEP 470 represents a simplification of the model to a model that many +users will be familar with, which is common amongst Linux distributions. + + +Switching to a repository structure breaks my workflow or isn't allowed by my host? +----------------------------------------------------------------------------------- + +There are a number of cheap or free hosts that would gladly support what is +required for a repository. In particular you don't actually need to upload your +files anywhere differently as long as you can generate a host with the correct +structure that points to where your files are actually located. Many of these +hosts provide free HTTPS using a shared domain name, and free HTTPS +certificates can be gotten from `StartSSL `_, or in +the near future `LetsEncrypt `_ or they may be gotten +cheap from any number of providers. + + +Why don't you provide ? +-------------------------- + +The answer here will depend on what is, however the answers typically are +one of: + +* We hadn't been thought of it and nobody had suggested it before. +* We don't have sufficient experience with to properly design a solution + for it and would welcome a domain expert to help us provide it. +* We're an open source project and nobody has decided to volunteer to design + and implement yet. + +Additional PEPs to propose additional features are always welcome, however they +would need someone with the time and expertise to accurately design . This +particular PEP is intended to focus on getting us to a point where the +capabilities of PyPI are straightforward with an easily understood baseline +that is similar to existing models such as Linux distribution repositories. Rejected Proposals @@ -327,9 +367,10 @@ instead return an error telling the end user about these extra URLs that they can add to their installer to make the installation work. -This idea is rejected because it provides a similar painful end user experience -where people will first attempt to install something, get an error, then have -to re-run the installation with the correct options. +This feature has been removed from the scope of the PEP because it proved too +difficult to develop a solution that avoided UX issues similar to those that +caused so many problems with the PEP 438 solution. If needed, a future PEP +could revisit this idea. Keep the current classification system but adjust the options -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 01:22:26 2015 From: python-checkins at python.org (donald.stufft) Date: Sat, 29 Aug 2015 23:22:26 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_incorrect_spelling_of_inh?= =?utf-8?q?erent?= Message-ID: <20150829232226.26529.57520@psf.io> https://hg.python.org/peps/rev/b94f9c419087 changeset: 6014:b94f9c419087 user: Donald Stufft date: Sat Aug 29 19:22:23 2015 -0400 summary: Fix incorrect spelling of inherent files: pep-0470.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -298,10 +298,10 @@ I can't host my project on PyPI because of , what should I do? ----------------------------------------------------------------- -First you should decide if is something inherient to PyPI, or if PyPI could +First you should decide if is something inherent to PyPI, or if PyPI could grow a feature to solve for you. If PyPI can add a feature to enable you to host your project on PyPI then you should propose that feature. However, if -is something inherient to PyPI, such as wanting to maintain control over your +is something inherent to PyPI, such as wanting to maintain control over your own files, then you should setup your own package repository and instruct your users in your project's description to add it to the list of repositories their installer of choice will use. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 05:27:55 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 30 Aug 2015 03:27:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0OTYy?= =?utf-8?q?=3A_Remove_space_from_filename?= Message-ID: <20150830032755.17322.71947@psf.io> https://hg.python.org/cpython/rev/3ef2d694e976 changeset: 97544:3ef2d694e976 branch: 2.7 parent: 97538:3639520c3fe9 user: Zachary Ware date: Sat Aug 29 22:25:04 2015 -0500 summary: Issue #24962: Remove space from filename files: Doc/using/mac.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -109,8 +109,9 @@ Python on OS X honors all standard Unix environment variables such as :envvar:`PYTHONPATH`, but setting these variables for programs started from the Finder is non-standard as the Finder does not read your :file:`.profile` or -:file:`.cshrc` at startup. You need to create a file :file:`~ -/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for details. +:file:`.cshrc` at startup. You need to create a file +:file:`~/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for +details. For more information on installation Python packages in MacPython, see section :ref:`mac-package-manager`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 05:27:55 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 30 Aug 2015 03:27:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2324962=3A_Merge_with_3=2E5?= Message-ID: <20150830032755.17322.55671@psf.io> https://hg.python.org/cpython/rev/5711ffc2292f changeset: 97547:5711ffc2292f parent: 97543:7996fa5f503f parent: 97546:84c3188f6e1e user: Zachary Ware date: Sat Aug 29 22:27:12 2015 -0500 summary: Closes #24962: Merge with 3.5 files: Doc/using/mac.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -102,8 +102,9 @@ Python on OS X honors all standard Unix environment variables such as :envvar:`PYTHONPATH`, but setting these variables for programs started from the Finder is non-standard as the Finder does not read your :file:`.profile` or -:file:`.cshrc` at startup. You need to create a file :file:`~ -/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for details. +:file:`.cshrc` at startup. You need to create a file +:file:`~/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for +details. For more information on installation Python packages in MacPython, see section :ref:`mac-package-manager`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 05:27:56 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 30 Aug 2015 03:27:56 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324962=3A_Merge_3=2E4?= Message-ID: <20150830032755.82407.94233@psf.io> https://hg.python.org/cpython/rev/84c3188f6e1e changeset: 97546:84c3188f6e1e branch: 3.5 parent: 97542:81222106eabe parent: 97545:2de6fba18ff6 user: Zachary Ware date: Sat Aug 29 22:26:54 2015 -0500 summary: Issue #24962: Merge 3.4 files: Doc/using/mac.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -102,8 +102,9 @@ Python on OS X honors all standard Unix environment variables such as :envvar:`PYTHONPATH`, but setting these variables for programs started from the Finder is non-standard as the Finder does not read your :file:`.profile` or -:file:`.cshrc` at startup. You need to create a file :file:`~ -/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for details. +:file:`.cshrc` at startup. You need to create a file +:file:`~/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for +details. For more information on installation Python packages in MacPython, see section :ref:`mac-package-manager`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 05:27:57 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 30 Aug 2015 03:27:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0OTYy?= =?utf-8?q?=3A_Remove_space_from_filename?= Message-ID: <20150830032755.4760.83410@psf.io> https://hg.python.org/cpython/rev/2de6fba18ff6 changeset: 97545:2de6fba18ff6 branch: 3.4 parent: 97532:a90c6d608b85 user: Zachary Ware date: Sat Aug 29 22:25:04 2015 -0500 summary: Issue #24962: Remove space from filename files: Doc/using/mac.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -102,8 +102,9 @@ Python on OS X honors all standard Unix environment variables such as :envvar:`PYTHONPATH`, but setting these variables for programs started from the Finder is non-standard as the Finder does not read your :file:`.profile` or -:file:`.cshrc` at startup. You need to create a file :file:`~ -/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for details. +:file:`.cshrc` at startup. You need to create a file +:file:`~/.MacOSX/environment.plist`. See Apple's Technical Document QA1067 for +details. For more information on installation Python packages in MacPython, see section :ref:`mac-package-manager`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 05:41:04 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 30 Aug 2015 03:41:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324272=3A_Merge_with_3=2E5?= Message-ID: <20150830034104.25347.33204@psf.io> https://hg.python.org/cpython/rev/10a63ded324c changeset: 97549:10a63ded324c parent: 97547:5711ffc2292f parent: 97548:192c654a7c93 user: Zachary Ware date: Sat Aug 29 22:40:37 2015 -0500 summary: Issue #24272: Merge with 3.5 files: Doc/library/typing.rst | 97 +++++++++++++++-------------- 1 files changed, 50 insertions(+), 47 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -20,8 +20,9 @@ def greeting(name: str) -> str: return 'Hello ' + name -In the function `greeting`, the argument `name` is expected to by of type `str` -and the return type `str`. Subtypes are accepted as arguments. +In the function ``greeting``, the argument ``name`` is expected to by of type +:class:`str` and the return type :class:`str`. Subtypes are accepted as +arguments. Type aliases ------------ @@ -49,8 +50,8 @@ It is possible to declare the return type of a callable without specifying the call signature by substituting a literal ellipsis -for the list of arguments in the type hint: `Callable[..., ReturnType]`. -`None` as a type hint is a special case and is replaced by `type(None)`. +for the list of arguments in the type hint: ``Callable[..., ReturnType]``. +``None`` as a type hint is a special case and is replaced by ``type(None)``. Generics -------- @@ -108,11 +109,12 @@ def log(self, message: str) -> None: self.logger.info('{}: {}'.format(self.name, message)) -`Generic[T]` as a base class defines that the class `LoggedVar` takes a single -type parameter `T` . This also makes `T` valid as a type within the class body. +``Generic[T]`` as a base class defines that the class ``LoggedVar`` takes a +single type parameter ``T`` . This also makes ``T`` valid as a type within the +class body. -The `Generic` base class uses a metaclass that defines `__getitem__` so that -`LoggedVar[t]` is valid as a type:: +The :class:`Generic` base class uses a metaclass that defines +:meth:`__getitem__` so that ``LoggedVar[t]`` is valid as a type:: from typing import Iterable @@ -132,7 +134,7 @@ class StrangePair(Generic[T, S]): ... -Each type variable argument to `Generic` must be distinct. +Each type variable argument to :class:`Generic` must be distinct. This is thus invalid:: from typing import TypeVar, Generic @@ -152,9 +154,9 @@ class LinkedList(Sized, Generic[T]): ... -Subclassing a generic class without specifying type parameters assumes `Any` -for each position. In the following example, `MyIterable` is not generic but -implicitly inherits from `Iterable[Any]`:: +Subclassing a generic class without specifying type parameters assumes +:class:`Any` for each position. In the following example, ``MyIterable`` is +not generic but implicitly inherits from ``Iterable[Any]``:: from typing import Iterable @@ -162,24 +164,24 @@ Generic metaclasses are not supported. -The `Any` type --------------- +The :class:`Any` type +--------------------- -A special kind of type is `Any`. Every type is a subtype of `Any`. -This is also true for the builtin type object. However, to the static type -checker these are completely different. +A special kind of type is :class:`Any`. Every type is a subtype of +:class:`Any`. This is also true for the builtin type object. However, to the +static type checker these are completely different. -When the type of a value is `object`, the type checker will reject almost all -operations on it, and assigning it to a variable (or using it as a return value) -of a more specialized type is a type error. On the other hand, when a value has -type `Any`, the type checker will allow all operations on it, and a value of -type `Any` can be assigned to a variable (or used as a return value) of a more -constrained type. +When the type of a value is :class:`object`, the type checker will reject +almost all operations on it, and assigning it to a variable (or using it as a +return value) of a more specialized type is a type error. On the other hand, +when a value has type :class:`Any`, the type checker will allow all operations +on it, and a value of type :class:`Any` can be assigned to a variable (or used +as a return value) of a more constrained type. Default argument values ----------------------- -Use a literal ellipsis `...` to declare an argument as having a default value:: +Use a literal ellipsis ``...`` to declare an argument as having a default value:: from typing import AnyStr @@ -195,9 +197,10 @@ Special type indicating an unconstrained type. - * Any object is an instance of `Any`. - * Any class is a subclass of `Any`. - * As a special case, `Any` and `object` are subclasses of each other. + * Any object is an instance of :class:`Any`. + * Any class is a subclass of :class:`Any`. + * As a special case, :class:`Any` and :class:`object` are subclasses of + each other. .. class:: TypeVar @@ -224,22 +227,22 @@ return x if len(x) >= len(y) else y The latter example's signature is essentially the overloading - of `(str, str) -> str` and `(bytes, bytes) -> bytes`. Also note - that if the arguments are instances of some subclass of `str`, - the return type is still plain `str`. + of ``(str, str) -> str`` and ``(bytes, bytes) -> bytes``. Also note + that if the arguments are instances of some subclass of :class:`str`, + the return type is still plain :class:`str`. - At runtime, `isinstance(x, T)` will raise `TypeError`. In general, - `isinstance` and `issublass` should not be used with types. + At runtime, ``isinstance(x, T)`` will raise :exc:`TypeError`. In general, + :func:`isinstance` and :func:`issublass` should not be used with types. Type variables may be marked covariant or contravariant by passing - `covariant=True` or `contravariant=True`. See :pep:`484` for more + ``covariant=True`` or ``contravariant=True``. See :pep:`484` for more details. By default type variables are invariant. .. class:: Union - Union type; `Union[X, Y]` means either X or Y. + Union type; ``Union[X, Y]`` means either X or Y. - To define a union, use e.g. `Union[int, str]`. Details: + To define a union, use e.g. ``Union[int, str]``. Details: * The arguments must be types and there must be at least one. @@ -259,37 +262,37 @@ Union[int, str] == Union[str, int] - * If `Any` is present it is the sole survivor, e.g.:: + * If :class:`Any` is present it is the sole survivor, e.g.:: Union[int, Any] == Any * You cannot subclass or instantiate a union. - * You cannot write `Union[X][Y]` + * You cannot write ``Union[X][Y]`` - * You can use `Optional[X]` as a shorthand for `Union[X, None]`. + * You can use ``Optional[X]`` as a shorthand for ``Union[X, None]``. .. class:: Optional Optional type. - `Optional[X]` is equivalent to `Union[X, type(None)]`. + ``Optional[X]`` is equivalent to ``Union[X, type(None)]``. .. class:: Tuple - Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + Tuple type; ``Tuple[X, Y]`` is the is the type of a tuple of two items with the first item of type X and the second of type Y. - Example: `Tuple[T1, T2]` is a tuple of two elements corresponding - to type variables T1 and T2. `Tuple[int, float, str]` is a tuple + Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding + to type variables T1 and T2. ``Tuple[int, float, str]`` is a tuple of an int, a float and a string. To specify a variable-length tuple of homogeneous type, - use literal ellipsis, e.g. `Tuple[int, ...]`. + use literal ellipsis, e.g. ``Tuple[int, ...]``. .. class:: Callable - Callable type; `Callable[[int], str]` is a function of (int) -> str. + Callable type; ``Callable[[int], str]`` is a function of (int) -> str. The subscription syntax must always be used with exactly two values: the argument list and the return type. The argument list @@ -297,9 +300,9 @@ There is no syntax to indicate optional or keyword arguments, such function types are rarely used as callback types. - `Callable[..., ReturnType]` could be used to type hint a callable - taking any number of arguments and returning `ReturnType`. - A plain `Callable` is equivalent to `Callable[..., Any]`. + ``Callable[..., ReturnType]`` could be used to type hint a callable + taking any number of arguments and returning ``ReturnType``. + A plain :class:`Callable` is equivalent to ``Callable[..., Any]``. .. class:: Generic -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 05:41:04 2015 From: python-checkins at python.org (zach.ware) Date: Sun, 30 Aug 2015 03:41:04 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy41KTogSXNzdWUgIzI0Mjcy?= =?utf-8?q?=3A_Remove_usage_of_default_reST_role_from_typing_docs?= Message-ID: <20150830034104.117772.56685@psf.io> https://hg.python.org/cpython/rev/192c654a7c93 changeset: 97548:192c654a7c93 branch: 3.5 parent: 97546:84c3188f6e1e user: Zachary Ware date: Sat Aug 29 22:39:47 2015 -0500 summary: Issue #24272: Remove usage of default reST role from typing docs files: Doc/library/typing.rst | 97 +++++++++++++++-------------- 1 files changed, 50 insertions(+), 47 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -20,8 +20,9 @@ def greeting(name: str) -> str: return 'Hello ' + name -In the function `greeting`, the argument `name` is expected to by of type `str` -and the return type `str`. Subtypes are accepted as arguments. +In the function ``greeting``, the argument ``name`` is expected to by of type +:class:`str` and the return type :class:`str`. Subtypes are accepted as +arguments. Type aliases ------------ @@ -49,8 +50,8 @@ It is possible to declare the return type of a callable without specifying the call signature by substituting a literal ellipsis -for the list of arguments in the type hint: `Callable[..., ReturnType]`. -`None` as a type hint is a special case and is replaced by `type(None)`. +for the list of arguments in the type hint: ``Callable[..., ReturnType]``. +``None`` as a type hint is a special case and is replaced by ``type(None)``. Generics -------- @@ -108,11 +109,12 @@ def log(self, message: str) -> None: self.logger.info('{}: {}'.format(self.name, message)) -`Generic[T]` as a base class defines that the class `LoggedVar` takes a single -type parameter `T` . This also makes `T` valid as a type within the class body. +``Generic[T]`` as a base class defines that the class ``LoggedVar`` takes a +single type parameter ``T`` . This also makes ``T`` valid as a type within the +class body. -The `Generic` base class uses a metaclass that defines `__getitem__` so that -`LoggedVar[t]` is valid as a type:: +The :class:`Generic` base class uses a metaclass that defines +:meth:`__getitem__` so that ``LoggedVar[t]`` is valid as a type:: from typing import Iterable @@ -132,7 +134,7 @@ class StrangePair(Generic[T, S]): ... -Each type variable argument to `Generic` must be distinct. +Each type variable argument to :class:`Generic` must be distinct. This is thus invalid:: from typing import TypeVar, Generic @@ -152,9 +154,9 @@ class LinkedList(Sized, Generic[T]): ... -Subclassing a generic class without specifying type parameters assumes `Any` -for each position. In the following example, `MyIterable` is not generic but -implicitly inherits from `Iterable[Any]`:: +Subclassing a generic class without specifying type parameters assumes +:class:`Any` for each position. In the following example, ``MyIterable`` is +not generic but implicitly inherits from ``Iterable[Any]``:: from typing import Iterable @@ -162,24 +164,24 @@ Generic metaclasses are not supported. -The `Any` type --------------- +The :class:`Any` type +--------------------- -A special kind of type is `Any`. Every type is a subtype of `Any`. -This is also true for the builtin type object. However, to the static type -checker these are completely different. +A special kind of type is :class:`Any`. Every type is a subtype of +:class:`Any`. This is also true for the builtin type object. However, to the +static type checker these are completely different. -When the type of a value is `object`, the type checker will reject almost all -operations on it, and assigning it to a variable (or using it as a return value) -of a more specialized type is a type error. On the other hand, when a value has -type `Any`, the type checker will allow all operations on it, and a value of -type `Any` can be assigned to a variable (or used as a return value) of a more -constrained type. +When the type of a value is :class:`object`, the type checker will reject +almost all operations on it, and assigning it to a variable (or using it as a +return value) of a more specialized type is a type error. On the other hand, +when a value has type :class:`Any`, the type checker will allow all operations +on it, and a value of type :class:`Any` can be assigned to a variable (or used +as a return value) of a more constrained type. Default argument values ----------------------- -Use a literal ellipsis `...` to declare an argument as having a default value:: +Use a literal ellipsis ``...`` to declare an argument as having a default value:: from typing import AnyStr @@ -195,9 +197,10 @@ Special type indicating an unconstrained type. - * Any object is an instance of `Any`. - * Any class is a subclass of `Any`. - * As a special case, `Any` and `object` are subclasses of each other. + * Any object is an instance of :class:`Any`. + * Any class is a subclass of :class:`Any`. + * As a special case, :class:`Any` and :class:`object` are subclasses of + each other. .. class:: TypeVar @@ -224,22 +227,22 @@ return x if len(x) >= len(y) else y The latter example's signature is essentially the overloading - of `(str, str) -> str` and `(bytes, bytes) -> bytes`. Also note - that if the arguments are instances of some subclass of `str`, - the return type is still plain `str`. + of ``(str, str) -> str`` and ``(bytes, bytes) -> bytes``. Also note + that if the arguments are instances of some subclass of :class:`str`, + the return type is still plain :class:`str`. - At runtime, `isinstance(x, T)` will raise `TypeError`. In general, - `isinstance` and `issublass` should not be used with types. + At runtime, ``isinstance(x, T)`` will raise :exc:`TypeError`. In general, + :func:`isinstance` and :func:`issublass` should not be used with types. Type variables may be marked covariant or contravariant by passing - `covariant=True` or `contravariant=True`. See :pep:`484` for more + ``covariant=True`` or ``contravariant=True``. See :pep:`484` for more details. By default type variables are invariant. .. class:: Union - Union type; `Union[X, Y]` means either X or Y. + Union type; ``Union[X, Y]`` means either X or Y. - To define a union, use e.g. `Union[int, str]`. Details: + To define a union, use e.g. ``Union[int, str]``. Details: * The arguments must be types and there must be at least one. @@ -259,37 +262,37 @@ Union[int, str] == Union[str, int] - * If `Any` is present it is the sole survivor, e.g.:: + * If :class:`Any` is present it is the sole survivor, e.g.:: Union[int, Any] == Any * You cannot subclass or instantiate a union. - * You cannot write `Union[X][Y]` + * You cannot write ``Union[X][Y]`` - * You can use `Optional[X]` as a shorthand for `Union[X, None]`. + * You can use ``Optional[X]`` as a shorthand for ``Union[X, None]``. .. class:: Optional Optional type. - `Optional[X]` is equivalent to `Union[X, type(None)]`. + ``Optional[X]`` is equivalent to ``Union[X, type(None)]``. .. class:: Tuple - Tuple type; `Tuple[X, Y]` is the is the type of a tuple of two items + Tuple type; ``Tuple[X, Y]`` is the is the type of a tuple of two items with the first item of type X and the second of type Y. - Example: `Tuple[T1, T2]` is a tuple of two elements corresponding - to type variables T1 and T2. `Tuple[int, float, str]` is a tuple + Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding + to type variables T1 and T2. ``Tuple[int, float, str]`` is a tuple of an int, a float and a string. To specify a variable-length tuple of homogeneous type, - use literal ellipsis, e.g. `Tuple[int, ...]`. + use literal ellipsis, e.g. ``Tuple[int, ...]``. .. class:: Callable - Callable type; `Callable[[int], str]` is a function of (int) -> str. + Callable type; ``Callable[[int], str]`` is a function of (int) -> str. The subscription syntax must always be used with exactly two values: the argument list and the return type. The argument list @@ -297,9 +300,9 @@ There is no syntax to indicate optional or keyword arguments, such function types are rarely used as callback types. - `Callable[..., ReturnType]` could be used to type hint a callable - taking any number of arguments and returning `ReturnType`. - A plain `Callable` is equivalent to `Callable[..., Any]`. + ``Callable[..., ReturnType]`` could be used to type hint a callable + taking any number of arguments and returning ``ReturnType``. + A plain :class:`Callable` is equivalent to ``Callable[..., Any]``. .. class:: Generic -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 05:44:39 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 30 Aug 2015 03:44:39 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_Build_on_498_inste?= =?utf-8?q?ad_of_competing?= Message-ID: <20150830034439.17314.31572@psf.io> https://hg.python.org/peps/rev/10a7d42cd65b changeset: 6015:10a7d42cd65b user: Nick Coghlan date: Sun Aug 30 13:44:31 2015 +1000 summary: PEP 501: Build on 498 instead of competing files: pep-0501.txt | 559 +++++++++++++++++++------------------- 1 files changed, 283 insertions(+), 276 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -6,9 +6,10 @@ Status: Draft Type: Standards Track Content-Type: text/x-rst +Requires: 498 Created: 08-Aug-2015 Python-Version: 3.6 -Post-History: 08-Aug-2015, 23-Aug-2015 +Post-History: 08-Aug-2015, 23-Aug-2015, 30-Aug-2015 Abstract ======== @@ -16,44 +17,53 @@ PEP 498 proposes new syntactic support for string interpolation that is transparent to the compiler, allow name references from the interpolation operation full access to containing namespaces (as with any other expression), -rather than being limited to explicitly name references. +rather than being limited to explicit name references. These are referred +to in the PEP as "f-strings" (a mnemonic for "formatted strings"). However, it only offers this capability for string formatting, making it likely we will see code like the following:: - os.system(f"echo {user_message}") + os.system(f"echo {message_from_user}") This kind of code is superficially elegant, but poses a significant problem -if the interpolated value ``user_message`` is in fact provided by a user: it's -an opening for a form of code injection attack, where the supplied user data -has not been properly escaped before being passed to the ``os.system`` call. +if the interpolated value ``message_from_user`` is in fact provided by an +untrusted user: it's an opening for a form of code injection attack, where +the supplied user data has not been properly escaped before being passed to +the ``os.system`` call. -To address that problem (and a number of other concerns), this PEP proposes an -alternative approach to compiler supported interpolation, using ``i`` (for -"interpolation") as the new string prefix and a substitution syntax -inspired by that used in ``string.Template`` and ES6 JavaScript, rather than -adding a 4th substitution variable syntax to Python. +To address that problem (and a number of other concerns), this PEP proposes +the complementary introduction of "i-strings" (a mnemonic for "interpolation +template strings"), where ``f"Message with {data}"`` would produce the same +result as ``format(i"Message with {data}")``. Some possible examples of the proposed syntax:: - msg = str(i'My age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.') - print(_(i"This is a $translated $message")) - translated = l20n(i"{{ $user }} is running {{ appname }}") - myquery = sql(i"SELECT $column FROM $table;") - mycommand = sh(i"cat $filename") - mypage = html(i"${response.body}") - callable = defer(i"$x + $y") + mycommand = sh(i"cat {filename}") + myquery = sql(i"SELECT {column} FROM {table};") + myresponse = html(i"{response.body}") + logging.debug(i"Message with {detailed} {debugging} {info}") Summary of differences from PEP 498 =================================== -The key differences of this proposal relative to PEP 498: +The key additions this proposal makes relative to PEP 498: -* "i" (interpolation template) prefix rather than "f" (formatted string) -* string.Template/JavaScript inspired substitution syntax, rather than str.format/C# inspired -* interpolation templates are created at runtime as a new kind of object -* the default rendering is invoked by calling ``str()`` on a template object - rather than automatically +* the "i" (interpolation template) prefix indicates delayed rendering, but + otherwise uses the same syntax and semantics as formatted strings +* interpolation templates are available at runtime as a new kind of object + (``types.InterpolationTemplate``) +* the default rendering used by formatted strings is invoked on an + interpolation template object by calling ``format(template)`` rather than + implicitly +* while f-string ``f"Message {here}"`` would be *semantically* equivalent to + ``format(i"Message {here}")``, it is expected that the explicit syntax would + avoid the runtime overhead of using the delayed rendering machinery + +NOTE: This proposal spells out a draft API for ``types.InterpolationTemplate``. +The precise details of the structures and methods exposed by this type would +be informed by the reference implementation of PEP 498, so it makes sense to +gain experience with that as an internal API before locking down a public API +(if this extension proposal is accepted). Proposal ======== @@ -61,38 +71,39 @@ This PEP proposes the introduction of a new string prefix that declares the string to be an interpolation template rather than an ordinary string:: - template = i"Substitute $names and ${expressions} at runtime" + template = i"Substitute {names} and {expressions()} at runtime" This would be effectively interpreted as:: - _raw_template = "Substitute $names and ${expressions} at runtime" - _parsed_fields = ( - ("Substitute ", 0, "names", "", ""), - (" and ", 1, "expressions", "", ""), - (" at runtime", None, None, None, None), + _raw_template = "Substitute {names} and {expressions()} at runtime" + _parsed_template = ( + ("Substitute ", "names"), + (" and ", "expressions()"), + (" at runtime", None), ) - _field_values = (names, expressions) + _field_values = (names, expressions()) + _format_specifiers = (f"", f"") template = types.InterpolationTemplate(_raw_template, - _parsed_fields, - _field_values) + _parsed_template, + _field_values, + _format_specifiers) -The ``__str__`` method on ``types.InterpolationTemplate`` would then implementat -the following ``str.format`` inspired semantics:: +The ``__format__`` method on ``types.InterpolationTemplate`` would then +implement the following ``str.format`` inspired semantics:: >>> import datetime >>> name = 'Jane' >>> age = 50 >>> anniversary = datetime.date(1991, 10, 12) - >>> str(i'My name is $name, my age next year is ${age+1}, my anniversary is ${anniversary:%A, %B %d, %Y}.') + >>> format(i'My name is {name}, my age next year is {age+1}, my anniversary is {anniversary:%A, %B %d, %Y}.') 'My name is Jane, my age next year is 51, my anniversary is Saturday, October 12, 1991.' - >>> str(i'She said her name is ${name!r}.') + >>> format(i'She said her name is {repr(name)}.') "She said her name is 'Jane'." -The interpolation template prefix can be combined with single-quoted, -double-quoted and triple quoted strings, including raw strings. It does not -support combination with bytes literals. +As with formatted strings, the interpolation template prefix can be combined with single-quoted, double-quoted and triple quoted strings, including raw strings. +It does not support combination with bytes literals. -This PEP does not propose to remove or deprecate any of the existing +Similarly, this PEP does not propose to remove or deprecate any of the existing string formatting mechanisms, as those will remain valuable when formatting strings that are not present directly in the source code of the application. @@ -105,38 +116,15 @@ situation where interpolating values into sensitive targets like SQL queries, shell commands and HTML templates will enjoy a much cleaner syntax when handled without regard for code injection attacks than when they are handled correctly. -It also has the effect of introducing yet another syntax for substitution -expressions into Python, when we already have 3 (``str.format``, -``bytes.__mod__`` and ``string.Template``) -This PEP proposes to handle the former issue by deferring the actual rendering -of the interpolation template to its ``__str__`` method (allow the use of -other template renderers by passing the template around as an object), and the -latter by adopting the ``string.Template`` substitution syntax defined in PEP -292. +This PEP proposes to provide the option of delaying the actual rendering +of an interpolation template to its ``__format__`` method, allowing the use of +other template renderers by passing the template around as a first class object. -The substitution syntax devised for PEP 292 is deliberately simple so that the -template strings can be extracted into an i18n message catalog, and passed to -translators who may not themselves be developers. For these use cases, it is -important that the interpolation syntax be as simple as possible, as the -translators are responsible for preserving the substition markers, even as -they translate the surrounding text. The PEP 292 syntax is also a common mesage -catalog syntax already supporting by many commercial software translation -support tools. - -PEP 498 correctly points out that the PEP 292 syntax isn't as flexible as that -introduced for general purpose string formatting in PEP 3101, so this PEP adds -that flexibility to the ``${ref}`` construct in PEP 292, and allows translation -tools the option of rejecting usage of that more advanced syntax at runtime, -rather than categorically rejecting it at compile time. The proposed permitted -expressions, conversion specifiers, and format specifiers inside ``${ref}`` are -exactly as defined for ``{ref}`` substituion in PEP 498. - -The specific proposal in this PEP is also deliberately close in both syntax -and semantics to the general purpose interpolation syntax introduced to -JavaScript in ES6, as we can reasonably expect a great many Python developers -to be regularly switching back and forth between user interface code written in -JavaScript and core application code written in Python. +While very different in the technical details, the +``types.InterpolationTemplate`` interface proposed in this PEP is +conceptually quite similar to the ``FormattableString`` type underlying the +`native interpolation `__ support introduced in C# 6.0. Specification @@ -150,141 +138,153 @@ permitted), and string literal concatenation operates as normal, with the entire combined literal forming the interpolation template. -The template string is parsed into literals and expressions. Expressions -appear as either identifiers prefixed with a single "$" character, or -surrounded be a leading '${' and a trailing '}. The parts of the format string -that are not expressions are separated out as string literals. +The template string is parsed into literals, expressions and format specifiers +as described for f-strings in PEP 498. Conversion specifiers are handled +by the compiler, and appear as part of the field text in interpolation +templates. -While parsing the string, any doubled ``$$`` is replaced with a single ``$`` -and is considered part of the literal text, rather than as introducing an -expression. - -These components are then organised into an instance of a new type with the +However, rather than being rendered directly into a formatted strings, these +components are instead organised into an instance of a new type with the following semantics:: class InterpolationTemplate: - __slots__ = ("raw_template", "parsed_fields", "field_values") + __slots__ = ("raw_template", "parsed_template", + "field_values", "format_specifiers") - def __new__(cls, raw_template, parsed_fields, field_values): + def __new__(cls, raw_template, parsed_template, + field_values, format_specifiers): self = super().__new__(cls) self.raw_template = raw_template - self.parsed_fields = parsed_fields + self.parsed_template = parsed_template self.field_values = field_values + self.format_specifiers = format_specifiers return self - def __iter__(self): - # Support iterable unpacking - yield self.raw_template - yield self.parsed_fields - yield self.field_values + def __repr__(self): + return (f"<{type(self).__qualname__} {repr(self._raw_template)} " + f"at {id(self):#x}>") - def __repr__(self): - return str(i"<${type(self).__qualname__} ${self.raw_template!r} " - "at ${id(self):#x}>") + def __format__(self, format_specifier): + # When formatted, render to a string, and use string formatting + return format(self.render(), format_specifier) - def __str__(self): - # See definition of the default template rendering below + def render(self, *, render_template=''.join, + render_field=format): + # See definition of the template rendering semantics below -The result of the interpolation template expression is an instance of this -type, rather than an already rendered string - default rendering only takes -place when the instance's ``__str__`` method is called. +The result of an interpolation template expression is an instance of this +type, rather than an already rendered string - rendering only takes +place when the instance's ``render`` method is called (either directly, or +indirectly via ``__format__``). -The format of the parsed fields tuple is inspired by the interface of -``string.Formatter.parse``, and consists of a series of 5-tuples each -containing: +The compiler will pass the following details to the interpolation template for +later use: -* a leading string literal (may be the empty string) -* the substitution field position (zero-based enumeration) -* the substitution expression text -* the substitution conversion specifier (as defined by str.format) -* the substitution format specifier (as defined by str.format) +* a string containing the raw template as written in the source code +* a parsed template tuple that allows the renderer to render the + template without needing to reparse the raw string template for substitution + fields +* a tuple containing the evaluated field values, in field substitution order +* a tuple containing the field format specifiers, in field substitution order -This field ordering is defined such that reading the parsed field tuples from -left to right will have all the subcomponents displayed in the same order as -they appear in the original template string. +This structure is designed to take full advantage of compile time constant +folding by ensuring the parsed template is always constant, even when the +field values and format specifiers include variable substitution expressions. -For ease of access the sequence elements will be available as attributes in -addition to being available by position: +The raw template is just the interpolation template as a string. By default, +it is used to provide an human readable representation for the interpolation +template. -* ``leading_text`` -* ``field_position`` -* ``expression`` -* ``conversion`` -* ``format`` +The parsed template consists of a tuple of 2-tuples, with each 2-tuple +containing the following fields: -The expression text is simply the text of the substitution expression, as it -appeared in the original string, but without the leading and/or surrounding -expression markers. The conversion specifier and format specifier are separated -from the substition expression by ``!`` and ``:`` as defined for ``str.format``. +* ``leading_text``: a leading string literal. This will be the empty string if + the current field is at the start of the string, or immediately follows the + preceding field. +* ``field_expr``: the text of the expression element in the substitution field. + This will be None for a final trailing text segment. -If a given substition field has no leading literal section, conversion specifier -or format specifier, then the corresponding elements in the tuple are the -empty string. If the final part of the string has no trailing substitution -field, then the field position, field expression, conversion specifier and -format specifier will all be ``None``. +The tuple of evaluated field values holds the *results* of evaluating the +substitution expressions in the scope where the interpolation template appears. -The substitution field values tuple is created by evaluating the interpolated -expressions in the exact runtime context where the interpolation expression -appears in the source code. +The tuple of field specifiers holds the *results* of evaluating the field +specifiers as f-strings in the scope where the interpolation template appears. -For the following example interpolation template:: +The ``InterpolationTemplate.render`` implementation then defines the rendering +process in terms of the following renderers: - i'abc${expr1:spec1}${expr2!r:spec2}def${expr3:!s}ghi $ident $$jkl' +* an overall ``render_template`` operation that defines how the sequence of + literal template sections and rendered fields are composed into a fully + rendered result. The default template renderer is string concatenation + using ``''.join``. +* a per field ``render_field`` operation that receives the field value and + format specifier for substitution fields within the template. The default + field renderer is the ``format`` builtin. -the parsed fields tuple would be:: +Given an appropriate parsed template representation and internal methods of +iterating over it, the semantics of template rendering would then be equivalent +to the following:: - ( - ('abc', 0, 'expr1', '', 'spec1'), - ('', 1, 'expr2', 'r', 'spec2'), - (def', 2, 'expr3', 's', ''), - ('ghi', 3, 'ident', '', ''), - ('$jkl', None, None, None, None) - ) + def render(self, *, render_template=''.join, + render_field=format): + iter_fields = enumerate(self.parsed_template) + values = self.field_values + specifiers = self.format_specifiers + template_parts = [] + for field_pos, (leading_text, field_expr) in iter_fields: + template_parts.append(leading_text) + if field_expr is not None: + value = values[field_pos] + specifier = specifiers[field_pos] + rendered_field = render_field(value, specifier) + template_parts.append(rendered_field) + return render_template(template_parts) -While the field values tuple would be:: +Conversion specifiers +--------------------- - (expr1, expr2, expr3, ident) +The ``!a``, ``!r`` and ``!s`` conversion specifiers supported by ``str.format`` +and hence PEP 498 are handled in interpolation templates as follows: -The parsed fields tuple can be constant folded at compile time, while the -expression values tuple will always need to be constructed at runtime. +* they're included unmodified in the raw template to ensure no information is + lost +* they're *replaced* in the parsed template with the corresponding builtin + calls, in order to ensure that ``field_expr`` always contains a valid + Python expression +* the corresponding field value placed in the field values tuple is + converted appropriately *before* being passed to the interpolation + template -The ``InterpolationTemplate.__str__`` implementation would have the following -semantics, with field processing being defined in terms of the ``format`` -builtin and ``str.format`` conversion specifiers:: +This means that, for most purposes, the difference between the use of +conversion specifiers and calling the corresponding builtins in the +original interpolation template will be transparent to custom renderers. The +difference will only be apparent if reparsing the raw template, or attempting +to reconstruct the original template from the parsed template. - _converter = string.Formatter().convert_field +Writing custom renderers +------------------------ - def __str__(self): - raw_template, fields, values = self - template_parts = [] - for leading_text, field_num, expr, conversion, format_spec in fields: - template_parts.append(leading_text) - if field_num is not None: - value = values[field_num] - if conversion: - value = _converter(value, conversion) - field_text = format(value, format_spec) - template_parts.append(field_str) - return "".join(template_parts) +Writing a custom renderer doesn't requiring any special syntax. Instead, +custom renderers are ordinary callables that process an interpolation +template directly either by calling the ``render()`` method with alternate ``render_template`` or ``render_field`` implementations, or by accessing the +template's data attributes directly. -Writing custom interpolators ----------------------------- +For example, the following function would render a template using objects' +``repr`` implementations rather than their native formatting support:: -Writing a custom interpolator doesn't requiring any special syntax. Instead, -custom interpolators are ordinary callables that process an interpolation -template directly based on the ``raw_template``, ``parsed_fields`` and -``field_values`` attributes, rather than relying on the default rendered. + def reprformat(template): + def render_field(value, specifier): + return format(repr(value), specifier) + return template.render(render_field=render_field) Expression evaluation --------------------- -The subexpressions that are extracted from the interpolation expression are -evaluated in the context where the interpolation expression appears. This means -the expression has full access to local, nonlocal and global variables. Any -valid Python expression can be used inside ``${}``, including function and -method calls. References without the surrounding braces are limited to looking -up single identifiers. +As with f-strings, the subexpressions that are extracted from the interpolation +template are evaluated in the context where the interpolation template +appears. This means the expression has full access to local, nonlocal and global variables. Any valid Python expression can be used inside ``{}``, including +function and method calls. Because the substitution expressions are evaluated where the string appears in the source code, there are no additional security concerns related to the @@ -295,7 +295,7 @@ >>> def foo(data): ... return data + 20 ... - >>> str(i'input=$bar, output=${foo(bar)}') + >>> str(i'input={bar}, output={foo(bar)}') 'input=10, output=30' Is essentially equivalent to:: @@ -306,37 +306,44 @@ Handling code injection attacks ------------------------------- -The proposed interpolation syntax makes it potentially attractive to write +The PEP 498 formatted string syntax makes it potentially attractive to write code like the following:: - myquery = str(i"SELECT $column FROM $table;") - mycommand = str(i"cat $filename") - mypage = str(i"${response.body}") + runquery(f"SELECT {column} FROM {table};") + runcommand(f"cat {filename}") + return_response(f"{response.body}") These all represent potential vectors for code injection attacks, if any of the variables being interpolated happen to come from an untrusted source. The specific proposal in this PEP is designed to make it straightforward to write -use case specific interpolators that take care of quoting interpolated values +use case specific renderers that take care of quoting interpolated values appropriately for the relevant security context:: - myquery = sql(i"SELECT $column FROM $table;") - mycommand = sh(i"cat $filename") - mypage = html(i"${response.body}") + runquery(sql(i"SELECT {column} FROM {table};")) + runcommand(sh(i"cat {filename}")) + return_response(html(i"{response.body}")) -This PEP does not cover adding such interpolators to the standard library, -but instead ensures they can be readily provided by third party libraries. +This PEP does not cover adding such renderers to the standard library +immediately, but rather proposes to ensure that they can be readily provided by +third party libraries, and potentially incorporated into the standard library +at a later date. -(Although it's tempting to propose adding InterpolationTemplate support at -least to ``subprocess.call``, ``subprocess.check_call`` and -``subprocess.check_output``) +For example, a renderer that aimed to offer a POSIX shell style experience for +accessing external programs, without the significant risks posed by running +``os.system`` or enabling the system shell when using the ``subprocess`` module +APIs, might provide an interface for running external programs similar to that +offered by the +`Julia programming language `__, +only with the backtick based ``\`cat $filename\``` syntax replaced by +``i"cat {filename}"`` style interpolation templates. -Format and conversion specifiers --------------------------------- +Format specifiers +----------------- -Aside from separating them out from the substitution expression, format and -conversion specifiers are otherwise treated as opaque strings by the -interpolation template parser - assigning semantics to those (or, alternatively, -prohibiting their use) is handled at runtime by the specified interpolator. +Aside from separating them out from the substitution expression during parsing, +format specifiers are otherwise treated as opaque strings by the interpolation +template parser - assigning semantics to those (or, alternatively, +prohibiting their use) is handled at runtime by the field renderer. Error handling -------------- @@ -348,13 +355,13 @@ Unmatched braces:: - >>> i'x=${x' + >>> i'x={x' File "", line 1 SyntaxError: missing '}' in interpolation expression Invalid expressions:: - >>> i'x=${!x}' + >>> i'x={!x}' File "", line 1 !x ^ @@ -364,68 +371,16 @@ template string before creating the interpolation template object. See PEP 498 for some examples. -Different interpolators may also impose additional runtime +Different renderers may also impose additional runtime constraints on acceptable interpolated expressions and other formatting details, which will be reported as runtime exceptions. -Internationalising interpolated strings -======================================= - -Since this PEP derives its interpolation syntax from the internationalisation -focused PEP 292, it's worth considering the potential implications this PEP -may have for the internationalisation use case. - -Internationalisation enters the picture by writing a custom interpolator that -performs internationalisation. For example, the following implementation -would delegate interpolation calls to ``string.Template``:: - - def i18n(template): - # A real implementation would also handle normal strings - raw_template, fields, values = template - translated = gettext.gettext(raw_template) - value_map = _build_interpolation_map(fields, values) - return string.Template(translated).safe_substitute(value_map) - - def _build_interpolation_map(fields, values): - field_values = {} - for literal_text, field_num, expr, conversion, format_spec in fields: - assert expr.isidentifier() and not conversion and not format_spec - if field_num is not None: - field_values[expr] = values[field_num] - return field_values - -And could then be invoked as:: - - # _ = i18n at top of module or injected into the builtins module - print(_(i"This is a $translated $message")) - -Any actual i18n implementation would need to address other issues (most notably -message catalog extraction), but this gives the general idea of what might be -possible. - -It's also worth noting that one of the benefits of the ``$`` based substitution -syntax in this PEP is its compatibility with Mozilla's -`l20n syntax `__, which uses ``{{ name }}`` for global -substitution, and ``{{ $user }}`` for local context substitution. - -With the syntax in this PEP, an l20n interpolator could be written as:: - - translated = l20n(i"{{ $user }} is running {{ appname }}") - -With the syntax proposed in PEP 498 (and neglecting the difficulty of doing -catalog lookups using PEP 498's semantics), the necessary brace escaping would -make the string look like this in order to interpolate the user variable -while preserving all of the expected braces:: - - locally_interpolated = f"{{{{ ${user} }}}} is running {{{{ appname }}}}" - - Possible integration with the logging module ============================================ -One of the challenges with the logging module has been that previously been -unable to devise a reasonable migration strategy away from the use of +One of the challenges with the logging module has been that we have previously +been unable to devise a reasonable migration strategy away from the use of printf-style formatting. The runtime parsing and interpolation overhead for logging messages also poses a problem for extensive logging of runtime events for monitoring purposes. @@ -434,13 +389,41 @@ could potentially be added to the logging module's event reporting APIs, permitting relevant details to be captured using forms like:: - logging.debug(i"Event: $event; Details: $data") - logging.critical(i"Error: $error; Details: $data") + logging.debug(i"Event: {event}; Details: {data}") + logging.critical(i"Error: {error}; Details: {data}") + +Rather than the current mod-formatting style:: + + logging.debug("Event: %s; Details: %s", event, data) + logging.critical("Error: %s; Details: %s", event, data) As the interpolation template is passed in as an ordinary argument, other -keyword arguments also remain available:: +keyword arguments would also remain available:: - logging.critical(i"Error: $error; Details: $data", exc_info=True) + logging.critical(i"Error: {error}; Details: {data}", exc_info=True) + +As part of any such integration, a recommended approach would need to be +defined for "lazy evaluation" of interpolated fields, as the ``logging`` +module's existing delayed interpolation support provides access to +`various attributes `__ of the event ``LogRecord`` instance. + +For example, since interpolation expressions are arbitrary Python expressions, +string literals could be used to indicate cases where evaluation itself is +being deferred, not just rendering:: + + logging.debug(i"Logger: {'record.name'}; Event: {event}; Details: {data}") + +This could be further extended with idioms like using inline tuples to indicate +deferred function calls to be made only if the log message is actually +going to be rendered at current logging levels:: + + logging.debug(i"Event: {event}; Details: {expensive_call, raw_data}") + +This kind of approach would be possible as having access to the actual *text* +of the field expression would allow the logging renderer to distinguish +between inline tuples that appear in the field expression itself, and tuples +that happen to be passed in as data values in a normal field. + Discussion ========== @@ -455,10 +438,10 @@ straightforward (the elements in the parsed fields tuple would just be byte strings rather than text strings, and the default renderer would be markedly less useful), but poses a signficant likelihood of producing -confusing type errors when a text interpolator was presented with +confusing type errors when a text renderer was presented with binary input. -Since the proposed operator is useful without binary interpolation support, and +Since the proposed syntax is useful without binary interpolation support, and such support can be readily added later, further consideration of binary interpolation is considered out of scope for the current PEP. @@ -466,19 +449,21 @@ ----------------------------------------- For interoperability with interfaces that only accept strings, interpolation -templates can be prerendered with ``str``, rather than delegating the rendering -to the called function. +templates can still be prerendered with ``format``, rather than delegating the +rendering to the called function. This reflects the key difference from PEP 498, which *always* eagerly applies -the default rendering, without any convenient way to decide to do something -different. +the default rendering, without any convenient way to delegate that choice to +another section of the code. Preserving the raw template string ---------------------------------- Earlier versions of this PEP failed to make the raw template string available -to interpolators. This greatly complicated the i18n example, as it needed to -reconstruct the original template to pass to the message catalog lookup. +on the interpolation template. Retaining it makes it possible to provide a more +attractive template representation, as well as providing the ability to +precisely reconstruct the original string, including both the expression text +and the details of any eagerly rendered substitution fields in format specifiers. Creating a rich object rather than a global name lookup ------------------------------------------------------- @@ -488,33 +473,52 @@ functions. Creating a rich descriptive object with a useful default renderer made it much easier to support customisation of the semantics of interpolation. -Relative order of conversion and format specifier in parsed fields ------------------------------------------------------------------- +Building atop PEP 498, rather than competing with it +---------------------------------------------------- -The relative order of the conversion specifier and the format specifier in the -substitution field 5-tuple is defined to match the order they appear in the -format string, which is unfortunately the inverse of the way they appear in the -``string.Formatter.parse`` 4-tuple. +Earlier versions of this PEP attempted to serve as a complete substitute for +PEP 498, rather than building a more flexible delayed rendering capability on +top of PEP 498's eager rendering. -I consider this a design defect in ``string.Formatter.parse``, so I think it's -worth fixing it in for the customer interpolator API, since the tuple already -has other differences (like including both the field position number *and* the -text of the expression). +Assuming the presence of f-strings as a supporting capability simplified a +number of aspects of the proposal in this PEP (such as how to handle substitution +fields in format specifiers) -This PEP also makes the parsed field attributes available by name, so it's -possible to write interpolators without caring about the precise field order -at all. +Deferring consideration of possible use in i18n use cases +--------------------------------------------------------- +The initial motivating use case for this PEP was providing a cleaner syntax +for i18n translation, as that requires access to the original unmodified +template. As such, it focused on compatibility with the subsitution syntax used +in Python's ``string.Template`` formatting and Mozilla's l20n project. + +However, subsequent discussion revealed there are significant additional +considerations to be taken into account in the i18n use case, which don't +impact the simpler cases of handling interpolation into security sensitive +contexts (like HTML, system shells, and database queries), or producing +application debugging messages in the preferred language of the development +team (rather than the native language of end users). + +Due to the original design of the ``str.format`` substitution syntax in PEP +3101 being inspired by C#'s string formatting syntax, the specific field +substitution syntax used in PEP 498 is consistent not only with Python's own ``str.format`` syntax, but also with string formatting in C#, including the +native "$-string" interpolation syntax introduced in C# 6.0 (released in July +2015). This means that while this particular substitution syntax may not +currently be widely used for translation of *Python* applications (losing out +to traditional %-formatting and the designed-specifically-for-i18n +``string.Template`` formatting), it *is* a popular translation format in the +wider software development ecosystem (since it is already the preferred +format for translating C# applications). Acknowledgements ================ * Eric V. Smith for creating PEP 498 and demonstrating the feasibility of arbitrary expression substitution in string interpolation -* Barry Warsaw for the string.Template syntax defined in PEP 292 -* Armin Ronacher for pointing me towards Mozilla's l20n project -* Mike Miller for his survey of programming language interpolation syntaxes in - PEP (TBD) +* Barry Warsaw, Armin Ronacher, and Mike Miller for their contributions to + exploring the feasibility of using this model of delayed rendering in i18n + use cases (even though the ultimate conclusion was that it was a poor fit, + at least for current approaches to i18n in Python) References ========== @@ -540,8 +544,11 @@ .. [#] PEP 498: Literal string formatting (https://www.python.org/dev/peps/pep-0498/) -.. [#] string.Formatter.parse - (https://docs.python.org/3/library/string.html#string.Formatter.parse) +.. [#] FormattableString and C# native string interpolation + (https://msdn.microsoft.com/en-us/library/dn961160.aspx) + +.. [#] Running external commands in Julia + (http://julia.readthedocs.org/en/latest/manual/running-external-programs/) Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 12:59:13 2015 From: python-checkins at python.org (nick.coghlan) Date: Sun, 30 Aug 2015 10:59:13 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_501=3A_Incorporate_feedba?= =?utf-8?q?ck_from_Eric_V=2E_Smith?= Message-ID: <20150830105913.82446.94665@psf.io> https://hg.python.org/peps/rev/607ea80f113c changeset: 6016:607ea80f113c user: Nick Coghlan date: Sun Aug 30 20:59:05 2015 +1000 summary: PEP 501: Incorporate feedback from Eric V. Smith files: pep-0501.txt | 30 ++++++++++++++++++++++++++++-- 1 files changed, 28 insertions(+), 2 deletions(-) diff --git a/pep-0501.txt b/pep-0501.txt --- a/pep-0501.txt +++ b/pep-0501.txt @@ -243,6 +243,17 @@ Conversion specifiers --------------------- +NOTE: + + Appropriate handling of conversion specifiers is currently an open question. + Exposing them more directly to custom renderers would increase the + complexity of the ``InterpolationTemplate`` definition without providing an + increase in expressiveness (since they're redundant with calling the builtins + directly). At the same time, they *are* made available as arbitary strings + when writing custom ``string.Formatter`` implementations, so it may be + desirable to offer similar levels of flexibility of interpretation in + interpolation templates. + The ``!a``, ``!r`` and ``!s`` conversion specifiers supported by ``str.format`` and hence PEP 498 are handled in interpolation templates as follows: @@ -277,6 +288,14 @@ return format(repr(value), specifier) return template.render(render_field=render_field) +When writing custom renderers, note that the return type of the overall +rendering operation is determined by the return type of the passed in ``render_template`` callable. While this is expected to be a string in most +cases, producing non-string objects *is* permitted. For example, a custom +template renderer could involve an ``sqlalchemy.sql.text`` call that produces +an `SQL Alchemy query object `__. + +Non-strings may also be returned from ``render_field``, as long as it is paired +with a ``render_template`` implementation that expects that behaviour. Expression evaluation --------------------- @@ -453,7 +472,7 @@ rendering to the called function. This reflects the key difference from PEP 498, which *always* eagerly applies -the default rendering, without any convenient way to delegate that choice to +the default rendering, without any way to delegate the choice of renderer to another section of the code. Preserving the raw template string @@ -503,7 +522,11 @@ 3101 being inspired by C#'s string formatting syntax, the specific field substitution syntax used in PEP 498 is consistent not only with Python's own ``str.format`` syntax, but also with string formatting in C#, including the native "$-string" interpolation syntax introduced in C# 6.0 (released in July -2015). This means that while this particular substitution syntax may not +2015). The related ``IFormattable`` interface in C# forms the basis of a +`number of elements `__ of C#'s internationalization and localization +support. + +This means that while this particular substitution syntax may not currently be widely used for translation of *Python* applications (losing out to traditional %-formatting and the designed-specifically-for-i18n ``string.Template`` formatting), it *is* a popular translation format in the @@ -547,6 +570,9 @@ .. [#] FormattableString and C# native string interpolation (https://msdn.microsoft.com/en-us/library/dn961160.aspx) +.. [#] IFormattable interface in C# (see remarks for globalization notes) + (https://msdn.microsoft.com/en-us/library/system.iformattable.aspx) + .. [#] Running external commands in Julia (http://julia.readthedocs.org/en/latest/manual/running-external-programs/) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 15:16:12 2015 From: python-checkins at python.org (eric.smith) Date: Sun, 30 Aug 2015 13:16:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Changed_title=2E?= Message-ID: <20150830131610.117778.24486@psf.io> https://hg.python.org/peps/rev/7c5c306723bd changeset: 6017:7c5c306723bd user: Eric V. Smith date: Sun Aug 30 09:16:20 2015 -0400 summary: Changed title. files: pep-0498.txt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pep-0498.txt b/pep-0498.txt --- a/pep-0498.txt +++ b/pep-0498.txt @@ -1,5 +1,5 @@ PEP: 498 -Title: Literal String Formatting +Title: Literal String Interpolation Version: $Revision$ Last-Modified: $Date$ Author: Eric V. Smith @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 01-Aug-2015 Python-Version: 3.6 -Post-History: 07-Aug-2015 +Post-History: 07-Aug-2015, 30-Aug-2015 Abstract ======== @@ -18,9 +18,9 @@ [#]_. Each of these methods have their advantages, but in addition have disadvantages that make them cumbersome to use in practice. This PEP proposed to add a new string formatting mechanism: Literal String -Formatting. In this PEP, such strings will be refered to as +Interpolation. In this PEP, such strings will be refered to as "f-strings", taken from the leading character used to denote such -strings. +strings, and standing for "formatted strings". This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 15:51:42 2015 From: python-checkins at python.org (donald.stufft) Date: Sun, 30 Aug 2015 13:51:42 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_a_FAQ_entry_to_PEP_470_on?= =?utf-8?q?_why_people_should_register_with_PyPI?= Message-ID: <20150830135141.82614.45121@psf.io> https://hg.python.org/peps/rev/2794fe98567d changeset: 6018:2794fe98567d user: Donald Stufft date: Sun Aug 30 09:51:38 2015 -0400 summary: Add a FAQ entry to PEP 470 on why people should register with PyPI files: pep-0470.txt | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/pep-0470.txt b/pep-0470.txt --- a/pep-0470.txt +++ b/pep-0470.txt @@ -355,6 +355,22 @@ that is similar to existing models such as Linux distribution repositories. +Why should I register on PyPI if I'm running my own repository anyways? +----------------------------------------------------------------------- + +PyPI serves two critical functions for the Python ecosystem. One of those is as +a central repository for the actual files that get downloaded and installed by +pip or another package manager and it is this function that this PEP is +concerned with and that you'd be replacing if you're running your own +repository. However, it also provides a central registry of who owns what name +in order to prevent naming collisions, think of it sort of as DNS but for +Python packages. In addition to making sure that names are handed out in a +first come, first serve manner it also provides a single place for users to go +to look search for and discover new projects. So the simple answer is, you +should still register your project with PyPI to avoid naming collisions and to +make it so people can still easily discover your project. + + Rejected Proposals ================== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Aug 30 18:17:08 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 30 Aug 2015 16:17:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge?= Message-ID: <20150830161708.25369.15646@psf.io> https://hg.python.org/cpython/rev/55bd86b0e333 changeset: 97551:55bd86b0e333 branch: 3.5 parent: 97548:192c654a7c93 parent: 97550:fa3ac31cfa44 user: Raymond Hettinger date: Sun Aug 30 09:15:36 2015 -0700 summary: merge files: Doc/library/collections.rst | 6 +++--- Lib/collections/__init__.py | 11 +---------- Lib/test/test_collections.py | 12 +++++++++++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -842,10 +842,10 @@ .. method:: somenamedtuple._asdict() Return a new :class:`OrderedDict` which maps field names to their corresponding - values. Note, this method is no longer needed now that the same effect can - be achieved by using the built-in :func:`vars` function:: + values:: - >>> vars(p) + >>> p = Point(x=11, y=22) + >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) .. versionchanged:: 3.1 diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -320,23 +320,14 @@ 'Return a nicely formatted representation string' return self.__class__.__name__ + '({repr_fmt})' % self - @property - def __dict__(self): - 'A new OrderedDict mapping field names to their values' - return OrderedDict(zip(self._fields, self)) - def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' - return self.__dict__ + return OrderedDict(zip(self._fields, self)) def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) - def __getstate__(self): - 'Exclude the OrderedDict from pickling' - return None - {field_defs} """ diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -257,7 +257,6 @@ self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method - self.assertEqual(vars(p), p._asdict()) # verify that vars() works try: p._replace(x=1, error=2) @@ -412,6 +411,17 @@ globals().pop('NTColor', None) # clean-up after this test + def test_namedtuple_subclass_issue_24931(self): + class Point(namedtuple('_Point', ['x', 'y'])): + pass + + a = Point(3, 4) + self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)])) + + a.w = 5 + self.assertEqual(a.__dict__, {'w': 5}) + + ################################################################################ ### Abstract Base Classes ################################################################################ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 18:17:09 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 30 Aug 2015 16:17:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <20150830161709.4774.63362@psf.io> https://hg.python.org/cpython/rev/c427f1b56ecb changeset: 97552:c427f1b56ecb parent: 97549:10a63ded324c parent: 97551:55bd86b0e333 user: Raymond Hettinger date: Sun Aug 30 09:17:02 2015 -0700 summary: merge files: Doc/library/collections.rst | 6 +++--- Lib/collections/__init__.py | 11 +---------- Lib/test/test_collections.py | 12 +++++++++++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -842,10 +842,10 @@ .. method:: somenamedtuple._asdict() Return a new :class:`OrderedDict` which maps field names to their corresponding - values. Note, this method is no longer needed now that the same effect can - be achieved by using the built-in :func:`vars` function:: + values:: - >>> vars(p) + >>> p = Point(x=11, y=22) + >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) .. versionchanged:: 3.1 diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -320,23 +320,14 @@ 'Return a nicely formatted representation string' return self.__class__.__name__ + '({repr_fmt})' % self - @property - def __dict__(self): - 'A new OrderedDict mapping field names to their values' - return OrderedDict(zip(self._fields, self)) - def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' - return self.__dict__ + return OrderedDict(zip(self._fields, self)) def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) - def __getstate__(self): - 'Exclude the OrderedDict from pickling' - return None - {field_defs} """ diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -257,7 +257,6 @@ self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method - self.assertEqual(vars(p), p._asdict()) # verify that vars() works try: p._replace(x=1, error=2) @@ -412,6 +411,17 @@ globals().pop('NTColor', None) # clean-up after this test + def test_namedtuple_subclass_issue_24931(self): + class Point(namedtuple('_Point', ['x', 'y'])): + pass + + a = Point(3, 4) + self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)])) + + a.w = 5 + self.assertEqual(a.__dict__, {'w': 5}) + + ################################################################################ ### Abstract Base Classes ################################################################################ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 18:17:08 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 30 Aug 2015 16:17:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0OTMx?= =?utf-8?q?=3A__Resolve_=5F=5Fdict=5F=5F_conflict_in_namedtuple_subclasses?= =?utf-8?q?=2E?= Message-ID: <20150830161708.117756.90922@psf.io> https://hg.python.org/cpython/rev/fa3ac31cfa44 changeset: 97550:fa3ac31cfa44 branch: 3.4 parent: 97545:2de6fba18ff6 user: Raymond Hettinger date: Sun Aug 30 09:13:48 2015 -0700 summary: Issue #24931: Resolve __dict__ conflict in namedtuple subclasses. files: Doc/library/collections.rst | 6 +++--- Lib/collections/__init__.py | 11 +---------- Lib/test/test_collections.py | 12 +++++++++++- Misc/NEWS | 4 ++++ 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -816,10 +816,10 @@ .. method:: somenamedtuple._asdict() Return a new :class:`OrderedDict` which maps field names to their corresponding - values. Note, this method is no longer needed now that the same effect can - be achieved by using the built-in :func:`vars` function:: + values:: - >>> vars(p) + >>> p = Point(x=11, y=22) + >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) .. versionchanged:: 3.1 diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -272,23 +272,14 @@ 'Return a nicely formatted representation string' return self.__class__.__name__ + '({repr_fmt})' % self - @property - def __dict__(self): - 'A new OrderedDict mapping field names to their values' - return OrderedDict(zip(self._fields, self)) - def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' - return self.__dict__ + return OrderedDict(zip(self._fields, self)) def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) - def __getstate__(self): - 'Exclude the OrderedDict from pickling' - return None - {field_defs} """ diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -225,7 +225,6 @@ self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method - self.assertEqual(vars(p), p._asdict()) # verify that vars() works try: p._replace(x=1, error=2) @@ -380,6 +379,17 @@ globals().pop('NTColor', None) # clean-up after this test + def test_namedtuple_subclass_issue_24931(self): + class Point(namedtuple('_Point', ['x', 'y'])): + pass + + a = Point(3, 4) + self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)])) + + a.w = 5 + self.assertEqual(a.__dict__, {'w': 5}) + + ################################################################################ ### Abstract Base Classes ################################################################################ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -78,6 +78,10 @@ - Issue #21112: Fix regression in unittest.expectedFailure on subclasses. Patch from Berker Peksag. +- Issue #24931: Instances of subclasses of namedtuples have their own __dict__ + which breaks the inherited __dict__ property and breaks the _asdict() method. + Removed the __dict__ property to prevent the conflict and fixed _asdict(). + - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 23:43:31 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 30 Aug 2015 21:43:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_merge_3=2E4_=28=2324963=29?= Message-ID: <20150830214331.27013.54810@psf.io> https://hg.python.org/cpython/rev/b5434aff4e84 changeset: 97554:b5434aff4e84 branch: 3.5 parent: 97551:55bd86b0e333 parent: 97553:a892c67fa0eb user: Benjamin Peterson date: Sun Aug 30 14:42:49 2015 -0700 summary: merge 3.4 (#24963) files: Doc/library/ipaddress.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -575,7 +575,7 @@ single-address network, with the network address being *address* and the mask being ``/128``. - 3. An integer packed into a :class:`bytes` object of length 16, bit-endian. + 3. An integer packed into a :class:`bytes` object of length 16, big-endian. The interpretation is similar to an integer *address*. 4. A two-tuple of an address description and a netmask, where the address -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 23:43:32 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 30 Aug 2015 21:43:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy41ICgjMjQ5NjMp?= Message-ID: <20150830214331.82752.92945@psf.io> https://hg.python.org/cpython/rev/6463279d1358 changeset: 97555:6463279d1358 parent: 97552:c427f1b56ecb parent: 97554:b5434aff4e84 user: Benjamin Peterson date: Sun Aug 30 14:42:59 2015 -0700 summary: merge 3.5 (#24963) files: Doc/library/ipaddress.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -575,7 +575,7 @@ single-address network, with the network address being *address* and the mask being ``/128``. - 3. An integer packed into a :class:`bytes` object of length 16, bit-endian. + 3. An integer packed into a :class:`bytes` object of length 16, big-endian. The interpretation is similar to an integer *address*. 4. A two-tuple of an address description and a netmask, where the address -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 23:43:31 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 30 Aug 2015 21:43:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_fix_spelling_t?= =?utf-8?q?hat_was_a_bit_confused_=28closes_=2324963=29?= Message-ID: <20150830214331.27007.62187@psf.io> https://hg.python.org/cpython/rev/a892c67fa0eb changeset: 97553:a892c67fa0eb branch: 3.4 parent: 97550:fa3ac31cfa44 user: Benjamin Peterson date: Sun Aug 30 14:42:38 2015 -0700 summary: fix spelling that was a bit confused (closes #24963) files: Doc/library/ipaddress.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -550,7 +550,7 @@ single-address network, with the network address being *address* and the mask being ``/128``. - 3. An integer packed into a :class:`bytes` object of length 16, bit-endian. + 3. An integer packed into a :class:`bytes` object of length 16, big-endian. The interpretation is similar to an integer *address*. An :exc:`AddressValueError` is raised if *address* is not a valid IPv6 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Aug 30 23:48:54 2015 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 30 Aug 2015 21:48:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Make_an_exampl?= =?utf-8?q?e_a_little_clearer?= Message-ID: <20150830214853.4752.78751@psf.io> https://hg.python.org/cpython/rev/62a3c600f3cf changeset: 97556:62a3c600f3cf branch: 2.7 parent: 97544:3ef2d694e976 user: Raymond Hettinger date: Sun Aug 30 14:48:42 2015 -0700 summary: Make an example a little clearer files: Doc/library/collections.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -696,6 +696,7 @@ Return a new :class:`OrderedDict` which maps field names to their corresponding values:: + >>> p = Point(x=11, y=22) >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 31 03:40:28 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 31 Aug 2015 01:40:28 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_a_sketch_ill?= =?utf-8?q?ustrating_a_=27fold=27=2E?= Message-ID: <20150831014028.17306.89550@psf.io> https://hg.python.org/peps/rev/394cc877bc89 changeset: 6019:394cc877bc89 user: Alexander Belopolsky date: Sun Aug 30 21:40:19 2015 -0400 summary: PEP 495: Added a sketch illustrating a 'fold'. files: pep-0495-fold.svg | 418 ++++++++++++++++++++++++++++++++++ pep-0495.txt | 5 + 2 files changed, 423 insertions(+), 0 deletions(-) diff --git a/pep-0495-fold.svg b/pep-0495-fold.svg new file mode 100644 --- /dev/null +++ b/pep-0495-fold.svg @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + UTC local + + + + + + + + + t + u0 + u1 + + + + + Fold + + diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -93,6 +93,11 @@ this PEP specifies how various functions should behave when given an invalid instance. +.. image:: pep-0495-fold.svg + :align: center + :width: 60% + + Affected APIs ------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 31 04:01:45 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 31 Aug 2015 02:01:45 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_=27Aware_dat?= =?utf-8?q?etime_instances=27_subsection=2E?= Message-ID: <20150831020145.109976.60388@psf.io> https://hg.python.org/peps/rev/987908def359 changeset: 6020:987908def359 user: Alexander Belopolsky date: Sun Aug 30 22:01:40 2015 -0400 summary: PEP 495: Added 'Aware datetime instances' subsection. files: pep-0495.txt | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -263,6 +263,21 @@ 1425796200.0 +Aware datetime instances +........................ + +Users of pre-PEP implementations of ``tzinfo`` will not see any +changes in the behavior of their aware datetime instances. Two such +instances that differ only by the value of the ``fold`` attribute will +not be distinguishable by any means other than an explicit access to +the ``fold`` value. + +On the other hand, if object's ``tzinfo`` is set to a fold-aware +implementation, then the value of ``fold`` will affect the result of +several methods but only if the corresponding time is in a fold or in +a gap: ``utcoffset()``, ``dst()``, ``tzname()``, and ``timetuple()``. + + Combining and splitting date and time ..................................... -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 31 04:15:13 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 31 Aug 2015 02:15:13 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Listed_additional_?= =?utf-8?q?affected_methods=2E?= Message-ID: <20150831021513.27013.13653@psf.io> https://hg.python.org/peps/rev/cbe0ec0530a5 changeset: 6021:cbe0ec0530a5 user: Alexander Belopolsky date: Sun Aug 30 22:15:10 2015 -0400 summary: PEP 495: Listed additional affected methods. files: pep-0495.txt | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -275,7 +275,9 @@ On the other hand, if object's ``tzinfo`` is set to a fold-aware implementation, then the value of ``fold`` will affect the result of several methods but only if the corresponding time is in a fold or in -a gap: ``utcoffset()``, ``dst()``, ``tzname()``, and ``timetuple()``. +a gap: ``utcoffset()``, ``dst()``, ``tzname()``, ``astimezone()``, +``strftime()`` (if "%Z" or "%z" directive is used in the format +specification), ``isoformat()``, and ``timetuple()``. Combining and splitting date and time -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 31 04:27:57 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 31 Aug 2015 02:27:57 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_png_rasteriz?= =?utf-8?q?ation_of_the_fold_sketch=2E?= Message-ID: <20150831022757.26987.56671@psf.io> https://hg.python.org/peps/rev/db95b4037a82 changeset: 6022:db95b4037a82 user: Alexander Belopolsky date: Sun Aug 30 22:27:51 2015 -0400 summary: PEP 495: Added png rasterization of the fold sketch. files: pep-0495-fold.png | Bin pep-0495.txt | 2 +- 2 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0495-fold.png b/pep-0495-fold.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7a41f601de01de65702b475c2593fc056e5e74ed GIT binary patch [stripped] diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -93,7 +93,7 @@ this PEP specifies how various functions should behave when given an invalid instance. -.. image:: pep-0495-fold.svg +.. image:: pep-0495-fold.* :align: center :width: 60% -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 31 04:38:23 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 31 Aug 2015 02:38:23 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_It_looks_like_=2Ep?= =?utf-8?q?ng_should_be_given_explicitly=2E?= Message-ID: <20150831023823.109992.68120@psf.io> https://hg.python.org/peps/rev/0ad635b52f16 changeset: 6023:0ad635b52f16 user: Alexander Belopolsky date: Sun Aug 30 22:38:20 2015 -0400 summary: PEP 495: It looks like .png should be given explicitly. files: pep-0495.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0495.txt b/pep-0495.txt --- a/pep-0495.txt +++ b/pep-0495.txt @@ -93,7 +93,7 @@ this PEP specifies how various functions should behave when given an invalid instance. -.. image:: pep-0495-fold.* +.. image:: pep-0495-fold.png :align: center :width: 60% -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 31 04:50:01 2015 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 31 Aug 2015 02:50:01 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_495=3A_Added_a_vertical_s?= =?utf-8?q?egment_to_the_graph=2E?= Message-ID: <20150831025000.17322.44378@psf.io> https://hg.python.org/peps/rev/8c8352ff4668 changeset: 6024:8c8352ff4668 user: Alexander Belopolsky date: Sun Aug 30 22:49:58 2015 -0400 summary: PEP 495: Added a vertical segment to the graph. files: pep-0495-fold.png | Bin pep-0495-fold.svg | 19 ++++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pep-0495-fold.png b/pep-0495-fold.png index 7a41f601de01de65702b475c2593fc056e5e74ed..d9fe8b6eeb680cf113a3097a6c93342a418ec087 GIT binary patch [stripped] diff --git a/pep-0495-fold.svg b/pep-0495-fold.svg --- a/pep-0495-fold.svg +++ b/pep-0495-fold.svg @@ -16,7 +16,10 @@ id="svg14800" version="1.1" inkscape:version="0.91 r13725" - sodipodi:docname="pep-0495-fold.svg"> + sodipodi:docname="pep-0495-fold.svg" + inkscape:export-filename="/Users/a/Work/peps/pep-0495-fold.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" /> Fold + -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Aug 31 05:43:48 2015 From: python-checkins at python.org (martin.panter) Date: Mon, 31 Aug 2015 03:43:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNSk6?= =?utf-8?q?_Issue_=2324952=3A_Merge_3=2E4_into_3=2E5?= Message-ID: <20150831034348.21285.47911@psf.io> https://hg.python.org/cpython/rev/606082fa2804 changeset: 97558:606082fa2804 branch: 3.5 parent: 97554:b5434aff4e84 parent: 97557:328383905eaf user: Martin Panter date: Mon Aug 31 03:25:34 2015 +0000 summary: Issue #24952: Merge 3.4 into 3.5 files: Doc/library/_thread.rst | 3 ++- Doc/library/threading.rst | 3 ++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -93,7 +93,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32 KiB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`RuntimeError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32 KiB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -89,7 +89,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32 KiB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`RuntimeError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32 KiB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -914,6 +914,7 @@ Simon Mathieu Laura Matson Graham Matthews +mattip Martin Matusiak Dieter Maurer Daniel May diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,9 @@ Documentation ------------- +- Issue #24952: Clarify the default size argument of stack_size() in + the "threading" and "_thread" modules. Patch from Mattip. + - Issue #23725: Overhaul tempfile docs. Note deprecated status of mktemp. Patch from Zbigniew J?drzejewski-Szmek. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 31 05:43:48 2015 From: python-checkins at python.org (martin.panter) Date: Mon, 31 Aug 2015 03:43:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0OTUy?= =?utf-8?q?=3A_Clarify_default_argument_of_stack=5Fsize=28=29_in_threading?= =?utf-8?b?LCBfdGhyZWFk?= Message-ID: <20150831034348.109966.42285@psf.io> https://hg.python.org/cpython/rev/328383905eaf changeset: 97557:328383905eaf branch: 3.4 parent: 97553:a892c67fa0eb user: Martin Panter date: Mon Aug 31 03:15:52 2015 +0000 summary: Issue #24952: Clarify default argument of stack_size() in threading, _thread Patch from Mattip. files: Doc/library/_thread.rst | 3 ++- Doc/library/threading.rst | 3 ++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -93,7 +93,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32 KiB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`RuntimeError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32 KiB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -89,7 +89,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32 KiB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`RuntimeError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32 KiB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -888,6 +888,7 @@ Simon Mathieu Laura Matson Graham Matthews +mattip Martin Matusiak Dieter Maurer Daniel May diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -456,6 +456,9 @@ Documentation ------------- +- Issue #24952: Clarify the default size argument of stack_size() in + the "threading" and "_thread" modules. Patch from Mattip. + - Issue #24808: Update the types of some PyTypeObject fields. Patch by Joseph Weston. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 31 05:43:48 2015 From: python-checkins at python.org (martin.panter) Date: Mon, 31 Aug 2015 03:43:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzI0OTUy?= =?utf-8?q?=3A_Clarify_default_argument_of_stack=5Fsize=28=29_in_threading?= =?utf-8?q?=2C_thread?= Message-ID: <20150831034348.26521.28002@psf.io> https://hg.python.org/cpython/rev/79afd50396c5 changeset: 97560:79afd50396c5 branch: 2.7 parent: 97556:62a3c600f3cf user: Martin Panter date: Mon Aug 31 03:40:59 2015 +0000 summary: Issue #24952: Clarify default argument of stack_size() in threading, thread Patch from Mattip. files: Doc/library/thread.rst | 3 ++- Doc/library/threading.rst | 3 ++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/thread.rst b/Doc/library/thread.rst --- a/Doc/library/thread.rst +++ b/Doc/library/thread.rst @@ -98,7 +98,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32kB). If changing the thread stack size is + integer value of at least 32,768 (32kB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, the :exc:`error` exception is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32kB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -194,7 +194,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32kB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`ThreadError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32kB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -875,6 +875,7 @@ Simon Mathieu Laura Matson Graham Matthews +mattip Martin Matusiak Dieter Maurer Daniel May diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -163,6 +163,9 @@ Documentation ------------- +- Issue #24952: Clarify the default size argument of stack_size() in + the "threading" and "thread" modules. Patch from Mattip. + - Issue #20769: Improve reload() docs. Patch by Dorian Pula. - Issue #23589: Remove duplicate sentence from the FAQ. Patch by Yongzhi Pan. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 31 05:43:50 2015 From: python-checkins at python.org (martin.panter) Date: Mon, 31 Aug 2015 03:43:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324952=3A_Merge_3=2E5_into_3=2E6?= Message-ID: <20150831034348.4750.33358@psf.io> https://hg.python.org/cpython/rev/501c9ab07996 changeset: 97559:501c9ab07996 parent: 97555:6463279d1358 parent: 97558:606082fa2804 user: Martin Panter date: Mon Aug 31 03:26:46 2015 +0000 summary: Issue #24952: Merge 3.5 into 3.6 files: Doc/library/_thread.rst | 3 ++- Doc/library/threading.rst | 3 ++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -93,7 +93,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32 KiB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`RuntimeError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32 KiB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -89,7 +89,8 @@ Return the thread stack size used when creating new threads. The optional *size* argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive - integer value of at least 32,768 (32 KiB). If changing the thread stack size is + integer value of at least 32,768 (32 KiB). If *size* is not specified, + 0 is used. If changing the thread stack size is unsupported, a :exc:`RuntimeError` is raised. If the specified stack size is invalid, a :exc:`ValueError` is raised and the stack size is unmodified. 32 KiB is currently the minimum supported stack size value to guarantee sufficient diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -914,6 +914,7 @@ Simon Mathieu Laura Matson Graham Matthews +mattip Martin Matusiak Dieter Maurer Daniel May diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,9 @@ Documentation ------------- +- Issue #24952: Clarify the default size argument of stack_size() in + the "threading" and "_thread" modules. Patch from Mattip. + Tests ----- -- Repository URL: https://hg.python.org/cpython From lp_benchmark_robot at intel.com Mon Aug 31 09:40:00 2015 From: lp_benchmark_robot at intel.com (lp_benchmark_robot) Date: Mon, 31 Aug 2015 07:40:00 +0000 Subject: [Python-checkins] Benchmark Results for Python Default 2015-08-31 Message-ID: <078AA0FFE8C7034097F90205717F504611D76A3F@IRSMSX102.ger.corp.intel.com> Results for project python_default-nightly, build date 2015-08-31 06:01:58 commit: 6463279d1358c3d49248ef14e36ef29d120dd51b revision date: 2015-08-31 00:42:59 environment: Haswell-EP cpu: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz 2x18 cores, stepping 2, LLC 45 MB mem: 128 GB os: CentOS 7.1 kernel: Linux 3.10.0-229.4.2.el7.x86_64 Baseline results were generated using release v3.4.3, with hash b4cbecbc0781e89a309d03b60a1f75f8499250e6 from 2015-02-25 12:15:33+00:00 ------------------------------------------------------------------------------------------ benchmark RSD* change since change since current rev with last run v3.4.3 regrtest PGO ------------------------------------------------------------------------------------------ :-) django_v2 0.40608% 0.21446% 8.14571% 19.04110% :-( pybench 0.19452% -0.02602% -2.45927% 9.15137% :-( regex_v8 2.86216% -0.14215% -3.17365% 4.53947% :-| nbody 0.13554% -0.46917% -1.33943% 10.33270% :-| json_dump_v2 0.31690% 1.73772% -1.04898% 12.85790% :-| normal_startup 1.11541% 0.28281% -0.40770% 5.37791% ------------------------------------------------------------------------------------------ Note: Benchmark results are measured in seconds. * Relative Standard Deviation (Standard Deviation/Average) Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. No license (express or implied, by estoppel or otherwise) to any intellectual property rights is granted by this document. Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade. This document may contain information on products, services and/or processes in development. Contact your Intel representative to obtain the latest forecast, schedule, specifications and roadmaps. The products and services described may contain defects or errors known as errata which may cause deviations from published specifications. Current characterized errata are available on request. (C) 2015 Intel Corporation. From python-checkins at python.org Mon Aug 31 17:45:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 31 Aug 2015 15:45:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E5_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy41?= Message-ID: <20150831154520.17302.40507@psf.io> https://hg.python.org/cpython/rev/afdfb9d53bec changeset: 97562:afdfb9d53bec parent: 97559:501c9ab07996 parent: 97561:833db9e2ed14 user: Yury Selivanov date: Mon Aug 31 11:45:11 2015 -0400 summary: Merge 3.5 files: Doc/library/asyncio.rst | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -4,6 +4,13 @@ .. module:: asyncio :synopsis: Asynchronous I/O, event loop, coroutines and tasks. +.. note:: + + The asyncio package has been included in the standard library on a + :term:`provisional basis `. Backwards incompatible + changes (up to and including removal of the module) may occur if deemed + necessary by the core developers. + .. versionadded:: 3.4 **Source code:** :source:`Lib/asyncio/` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 31 17:45:48 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 31 Aug 2015 15:45:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E5=29=3A_Make_asyncio_p?= =?utf-8?q?rovisional?= Message-ID: <20150831154520.21273.4388@psf.io> https://hg.python.org/cpython/rev/833db9e2ed14 changeset: 97561:833db9e2ed14 branch: 3.5 parent: 97558:606082fa2804 user: Yury Selivanov date: Mon Aug 31 11:42:31 2015 -0400 summary: Make asyncio provisional files: Doc/library/asyncio.rst | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -4,6 +4,13 @@ .. module:: asyncio :synopsis: Asynchronous I/O, event loop, coroutines and tasks. +.. note:: + + The asyncio package has been included in the standard library on a + :term:`provisional basis `. Backwards incompatible + changes (up to and including removal of the module) may occur if deemed + necessary by the core developers. + .. versionadded:: 3.4 **Source code:** :source:`Lib/asyncio/` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Aug 31 19:26:26 2015 From: python-checkins at python.org (chris.angelico) Date: Mon, 31 Aug 2015 17:26:26 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Allocate_PEP_502_for_Mike_Mil?= =?utf-8?q?ler=27s_proposal?= Message-ID: <20150831172626.19109.82975@psf.io> https://hg.python.org/peps/rev/e980e47d452f changeset: 6025:e980e47d452f user: Chris Angelico date: Tue Sep 01 03:26:19 2015 +1000 summary: Allocate PEP 502 for Mike Miller's proposal files: pep-0502.txt | 846 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 846 insertions(+), 0 deletions(-) diff --git a/pep-0502.txt b/pep-0502.txt new file mode 100644 --- /dev/null +++ b/pep-0502.txt @@ -0,0 +1,846 @@ +PEP: 502 +Title: String Interpolation Redux +Version: $Revision$ +Last-Modified: $Date$ +Author: Mike G. Miller +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 10-Aug-2015 +Python-Version: 3.6 + +Note: Open issues below are stated with a question mark (?), +and are therefore searchable. + + +Abstract +======== + +This proposal describes a new string interpolation feature for Python, +called an *expression-string*, +that is both concise and powerful, +improves readability in most cases, +yet does not conflict with existing code. + +To achieve this end, +a new string prefix is introduced, +which expands at compile-time into an equivalent expression-string object, +with requested variables from its context passed as keyword arguments. +At runtime, +the new object uses these passed values to render a string to given +specifications, building on `the existing syntax`_ of ``str.format()``:: + + >>> location = 'World' + >>> e'Hello, {location} !' # new prefix: e'' + 'Hello, World !' # interpolated result + +.. _the existing syntax: https://docs.python.org/3/library/string.html#format-string-syntax + +This PEP does not recommend to remove or deprecate any of the existing string +formatting mechanisms. + + +Motivation +========== + +Though string formatting and manipulation features are plentiful in Python, +one area where it falls short +is the lack of a convenient string interpolation syntax. +In comparison to other dynamic scripting languages +with similar use cases, +the amount of code necessary to build similar strings is substantially higher, +while at times offering lower readability due to verbosity, dense syntax, +or identifier duplication. [1]_ + +Furthermore, replacement of the print statement with the more consistent print +function of Python 3 (PEP 3105) has added one additional minor burden, +an additional set of parentheses to type and read. +Combined with the verbosity of current formatting solutions, +this puts an otherwise simple language at an unfortunate disadvantage to its +peers:: + + echo "Hello, user: $user, id: $id, on host: $hostname" # bash + say "Hello, user: $user, id: $id, on host: $hostname"; # perl + puts "Hello, user: #{user}, id: #{id}, on host: #{hostname}\n" # ruby + # 80 ch -->| + # Python 3, str.format with named parameters + print('Hello, user: {user}, id: {id}, on host: {hostname}'.format(**locals())) + + # Python 3, variation B, worst case + print('Hello, user: {user}, id: {id}, on host: {hostname}'.format(user=user, + id=id, + hostname= + hostname)) + +In Python, the formatting and printing of a string with multiple variables in a +single line of code of standard width is noticeably harder and more verbose, +indentation often exacerbating the issue. + +For use cases such as smaller projects, systems programming, +shell script replacements, and even one-liners, +where message formatting complexity has yet to be encapsulated, +this verbosity has likely lead a significant number of developers and +administrators to choose other languages over the years. + + +Rationale +========= + + +Naming +------ + +The term expression-string was chosen because other applicable terms, +such as format-string and template are already well used in the Python standard +library. + +The string prefix itself, ``e''`` was chosen to demonstrate that the +specification enables expressions, +is not limited to ``str.format()`` syntax, +and also does not lend itself to `the shorthand term`_ "f-string". +It is also slightly easier to type than other choices such as ``_''`` and +``i''``, +while perhaps `less odd-looking`_ to C-developers. +``printf('')`` vs. ``print(f'')``. + +.. _the shorthand term: reference_needed +.. _less odd-looking: https://mail.python.org/pipermail/python-dev/2015-August/141147.html + + + +Goals +------------- + +The design goals of expression-strings are as follows: + +#. Eliminate need to pass variables manually. +#. Eliminate repetition of identifiers and redundant parentheses. +#. Reduce awkward syntax, punctuation characters, and visual noise. +#. Improve readability and eliminate mismatch errors, + by prefering named parameters to positional arguments. +#. Avoid need for ``locals()`` and ``globals()`` usage, + instead parsing the given string for named parameters, + then passing them automatically. [2]_ [3]_ + + +Limitations +------------- + +In contrast to other languages that take design cues from Unix and its +shells, +and in common with Javascript, +Python specified both single (``'``) and double (``"``) ASCII quote +characters to enclose strings. +It is not reasonable to choose one of them now to enable interpolation, +while leaving the other for uninterpolated strings. +"Backtick" characters (`````) are also `constrained by history`_ as a shortcut +for ``repr()``. + +This leaves a few remaining options for the design of such a feature: + +* An operator, as in printf-style string formatting via ``%``. +* A class, such as ``string.Template()``. +* A function, such as ``str.format()``. +* New syntax +* A new string prefix marker, such as the well-known ``r''`` or ``u''``. + +The first three options above currently work well. +Each has specific use cases and drawbacks, +yet also suffer from the verbosity and visual noise mentioned previously. +All are discussed in the next section. + +.. _constrained by history: https://mail.python.org/pipermail/python-ideas/2007-January/000054.html + +Background +------------- + +This proposal builds on several existing techniques and proposals and what +we've collectively learned from them. + +The following examples focus on the design goals of readability and +error-prevention using named parameters. +Let's assume we have the following dictionary, +and would like to print out its items as an informative string for end users:: + + >>> params = {'user': 'nobody', 'id': 9, 'hostname': 'darkstar'} + + +Printf-style formatting +''''''''''''''''''''''' + +This `venerable technique`_ continues to have its uses, +such as with byte-based protocols, +simplicity in simple cases, +and familiarity to many programmers:: + + >>> 'Hello, user: %(user)s, id: %(id)s, on host: %(hostname)s' % params + 'Hello, user: nobody, id: 9, on host: darkstar' + +In this form, considering the prerequisite dictionary creation, +the technique is verbose, a tad noisy, +and relatively readable. +Additional issues are that an operator can only take one argument besides the +original string, +meaning multiple parameters must be passed in a tuple or dictionary. +Also, it is relatively easy to make an error in the number of arguments passed, +the expected type, +have a missing key, +or forget the trailing type, e.g. (``s`` or ``d``). + +.. _venerable technique: https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting + + +string.Template +''''''''''''''' + +The ``string.Template`` `class from`_ PEP 292 +(Simpler String Substitutions) +is a purposely simplified design, +using familiar shell interpolation syntax, +with `safe-substitution feature`_, +that finds its main use cases in shell and internationalization tools:: + + Template('Hello, user: $user, id: ${id}, on host: $hostname').substitute(params) + +Also verbose, however the string itself is readable. +Though functionality is limited, +it meets its requirements well. +It isn't powerful enough for many cases, +and that helps keep inexperienced users out of trouble, +as well as avoiding issues with moderately-trusted input (i18n) from +third-parties. +It unfortunately takes enough code to discourage its use for ad-hoc string +interpolation, +unless encapsulated in a `convenience library`_ such as ``flufl.i18n``. + +.. _class from: https://docs.python.org/3/library/string.html#template-strings +.. _safe-substitution feature: https://docs.python.org/3/library/string.html#string.Template.safe_substitute +.. _convenience library: http://pythonhosted.org/flufl.i18n/ + + +PEP 215 - String Interpolation +'''''''''''''''''''''''''''''' + +PEP 215 was a former proposal of which this one shares a lot in common. +Apparently, the world was not ready for it at the time, +but considering recent support in a number of other languages, +its day may have come. + +The large number of dollar sign (``$``) characters it included may have +led it to resemble Python's arch-nemesis Perl, +and likely contributed to the PEP's lack of acceptance. +It was superseded by the following proposal. + + +str.format() +'''''''''''' + +The ``str.format()`` `syntax of`_ PEP 3101 is the most recent and modern of the +existing options. +It is also more powerful and usually easier to read than the others. +It avoids many of the drawbacks and limits of the previous techniques. + +However, due to its necessary function call and parameter passing, +it runs from verbose to very verbose in various situations with +string literals:: + + >>> 'Hello, user: {user}, id: {id}, on host: {hostname}'.format(**params) + 'Hello, user: nobody, id: 9, on host: darkstar' + + # when using keyword args, var name shortening sometimes needed to fit :/ + >>> 'Hello, user: {user}, id: {id}, on host: {host}'.format(user=user, + id=id, + host=hostname) + 'Hello, user: nobody, id: 9, on host: darkstar' + +.. _syntax of: https://docs.python.org/3/library/string.html#format-string-syntax + + +PEP 498 -- Literal String Formatting +'''''''''''''''''''''''''''''''''''' + +PEP 498 discusses and delves partially into implementation details of +expression-strings, +which it calls f-strings, +the idea and syntax +(with exception of the prefix letter) +of which is identical to that discussed here. +The resulting compile-time transformation however +returns a string joined from parts at runtime, +rather than an object. + +It also, somewhat controversially to those first exposed to it, +introduces the idea that these strings shall be augmented with support for +arbitrary expressions, +which is discussed further in the following sections. + + +PEP 501 -- Translation ready string interpolation +''''''''''''''''''''''''''''''''''''''''''''''''' + +The complimentary PEP 501 brings internationalization into the discussion as a +first-class concern, with its proposal of i-strings, +``string.Template`` syntax integration compatible with ES6 (Javascript), +deferred rendering, +and a similar object return value. + + +Implementations in Other Languages +---------------------------------- + +String interpolation is now well supported by various programming languages +used in multiple industries, +and is converging into a standard of sorts. +It is centered around ``str.format()`` style syntax in minor variations, +with the addition of arbitrary expressions to expand utility. + +In the `Motivation`_ section it was shown how convenient interpolation syntax +existed in Bash, Perl, and Ruby. +Let's take a look at their expression support. + + +Bash +'''' + +Bash supports a number of arbitrary, even recursive constructs inside strings:: + + > echo "user: $USER, id: $((id + 6)) on host: $(echo is $(hostname))" + user: nobody, id: 15 on host: is darkstar + +* Explicit interpolation within double quotes. +* Direct environment variable access supported. +* Arbitrary expressions are supported. [4]_ +* External process execution and output capture supported. [5]_ +* Recursive expressions are supported. + + +Perl +'''' + + +Perl also has arbitrary expression constructs, perhaps not as well known:: + + say "I have @{[$id + 6]} guanacos."; # lists + say "I have ${\($id + 6)} guanacos."; # scalars + say "Hello { @names.join(', ') } how are you?"; # Perl 6 version + +* Explicit interpolation within double quotes. +* Arbitrary expressions are supported. [6]_ [7]_ + + +Ruby +'''' + +Ruby allows arbitrary expressions in its interpolated strings:: + + puts "One plus one is two: #{1 + 1}\n" + +* Explicit interpolation within double quotes. +* Arbitrary expressions are supported. [8]_ [9]_ +* Possible to change delimiter chars with ``%``. +* See the Reference Implementation(s) section for an implementation in Python. + + +Others +'''''' + +Let's look at some less-similar modern languages recently implementing string +interpolation. + + +Scala +''''' + +`Scala interpolation`_ is directed through string prefixes. +Each prefix has a different result:: + + s"Hello, $name ${1 + 1}" # arbitrary + f"$name%s is $height%2.2f meters tall" # printf-style + raw"a\nb" # raw, like r'' + +These prefixes may also be implemented by the user, +by extending Scala's ``StringContext`` class. + +* Explicit interpolation within double quotes with literal prefix. +* User implemented prefixes supported. +* Arbitrary expressions are supported. + +.. _Scala interpolation: http://docs.scala-lang.org/overviews/core/string-interpolation.html + + +ES6 (Javascript) +''''''''''''''''''' + +Designers of `Template strings`_ faced the same issue as Python where single +and double quotes were taken. +Unlike Python however, "backticks" were not. +They were chosen as part of the ECMAScript 2015 (ES6) standard:: + + console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`); + +Custom prefixes are also supported by implementing a function the same name +as the tag:: + + function tag(strings, ...values) { + console.log(strings.raw[0]); // raw string is also available + return "Bazinga!"; + } + tag`Hello ${ a + b } world ${ a * b}`; + +* Explicit interpolation within backticks. +* User implemented prefixes supported. +* Arbitrary expressions are supported. + +.. _Template strings: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings + +C#, Version 6 +''''''''''''' + +C# has a useful new `interpolation feature`_ as well, +with some ability to `customize interpolation`_ via the ``IFormattable`` +interface:: + + $"{person.Name, 20} is {person.Age:D3} year{(p.Age == 1 ? "" : "s")} old."; + +* Explicit interpolation with double quotes and ``$`` prefix. +* Custom interpolations are available. +* Arbitrary expressions are supported. + +.. _interpolation feature: https://msdn.microsoft.com/en-us/library/Dn961160.aspx +.. _customize interpolation: http://www.thomaslevesque.com/2015/02/24/customizing-string-interpolation-in-c-6/ + +Apple's Swift +''''''''''''' + +Arbitrary `interpolation under Swift`_ is available on all strings:: + + let multiplier = 3 + let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" + // message is "3 times 2.5 is 7.5" + +* Implicit interpolation with double quotes. +* Arbitrary expressions are supported. +* Cannot contain CR/LF. + +.. _interpolation under Swift: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID292 + + +Additional examples +''''''''''''''''''' + +A number of additional examples may be `found at Wikipedia`_. + +.. _found at Wikipedia: https://en.wikipedia.org/wiki/String_interpolation#Examples + +Now that background and imlementation history have been covered, +let's continue on for a solution. + + +New Syntax +---------- + +This should be an option of last resort, +as every new syntax feature has a cost in terms of real-estate in a brain it +inhabits. +There is one alternative left on our list of possibilities, +which follows. + + +New String Prefix +----------------- + +Given the history of string formatting in Python, +backwards-compatibility, +implementations in other languages, +and the avoidance of new syntax unless necessary, +an acceptable design is reached through elimination +rather than unique insight. +Therefore, we choose to explicitly mark interpolated string literals with a +string prefix. + +We also choose an expression syntax that reuses and builds on the strongest of +the existing choices, +``str.format()`` to avoid further duplication. + + +Specification +============= + +String literals with the prefix of ``e`` shall be converted at compile-time to +the construction of an ``estr`` (perhaps ``types.ExpressionString``?) object. +Strings and values are parsed from the literal and passed as tuples to the +constructor:: + + >>> location = 'World' + >>> e'Hello, {location} !' + + # becomes + # estr('Hello, {location} !', # template + ('Hello, ', ' !'), # string fragments + ('location',), # expressions + ('World',), # values + ) + +The object interpolates its result immediately at run-time:: + + 'Hello, World !' + + +ExpressionString Objects +------------------------ + +The ExpressionString object supports both immediate and deferred rendering of +its given template and parameters. +It does this by immediately rendering its inputs to its internal string and +``.rendered`` string member (still necessary?), +useful in the majority of use cases. +To allow for deferred rendering and caller-specified escaping, +all inputs are saved for later inspection, +with convenience methods available. + +Notes: + +* Inputs are saved to the object as ``.template`` and ``.context`` members + for later use. +* No explicit ``str(estr)`` call is necessary to render the result, + though doing so might be desired to free resources if significant. +* Additional or deferred rendering is available through the ``.render()`` + method, which allows template and context to be overriden for flexibility. +* Manual escaping of potentially dangerous input is available through the + ``.escape(escape_function)`` method, + the rules of which may therefore be specified by the caller. + The given function should both accept and return a single modified string. + +* A sample Python implementation can `found at Bitbucket`_: + +.. _found at Bitbucket: https://bitbucket.org/mixmastamyk/docs/src/default/pep/estring_demo.py + + +Inherits From ``str`` Type +''''''''''''''''''''''''''' + +Inheriting from the ``str`` class is one of the techniques available to improve +compatibility with code expecting a string object, +as it will pass an ``isinstance(obj, str)`` test. +ExpressionString implements this and also renders its result into the "raw" +string of its string superclass, +providing compatibility with a majority of code. + + +Interpolation Syntax +-------------------- + +The strongest of the existing string formatting syntaxes is chosen, +``str.format()`` as a base to build on. [10]_ [11]_ + +.. + +* Additionally, single arbitrary expressions shall also be supported inside + braces as an extension:: + + >>> e'My age is {age + 1} years.' + + See below for section on safety. + +* Triple quoted strings with multiple lines shall be supported:: + + >>> e'''Hello, + {location} !''' + 'Hello,\n World !' + +* Adjacent implicit concatenation shall be supported; + interpolation does not `not bleed into`_ other strings:: + + >>> 'Hello {1, 2, 3} ' e'{location} !' + 'Hello {1, 2, 3} World !' + +* Additional implementation details, + for example expression and error-handling, + are specified in the compatible PEP 498. + +.. _not bleed into: https://mail.python.org/pipermail/python-ideas/2015-July/034763.html + + +Composition with Other Prefixes +------------------------------- + +* Expression-strings apply to unicode objects only, + therefore ``u''`` is never needed. + Should it be prevented? + +* Bytes objects are not included here and do not compose with e'' as they + do not support ``__format__()``. + +* Complimentary to raw strings, + backslash codes shall not be converted in the expression-string, + when combined with ``r''`` as ``re''``. + + +Examples +-------- + +A more complicated example follows:: + + n = 5; # t0, t1 = ? TODO + a = e"Sliced {n} onions in {t1-t0:.3f} seconds." + # returns the equvalent of + estr("Sliced {n} onions in {t1-t0:.3f} seconds", # template + ('Sliced ', ' onions in ', ' seconds'), # strings + ('n', 't1-t0:.3f'), # expressions + (5, 0.555555) # values + ) + +With expressions only:: + + b = e"Three random numbers: {rand()}, {rand()}, {rand()}." + # returns the equvalent of + estr("Three random numbers: {rand():f}, {rand():f}, {rand():}.", # template + ('Three random numbers: ', ', ', ', ', '.'), # strings + ('rand():f', 'rand():f', 'rand():f'), # expressions + (rand(), rand(), rand()) # values + ) + + +Safety +----------- + +In this section we will describe the safety situation and precautions taken +in support of expression-strings. + +#. Only string literals shall be considered here, + not variables to be taken as input or passed around, + making external attacks difficult to accomplish. + + * ``str.format()`` `already handles`_ this use-case. + * Direct instantiation of the ExpressionString object with non-literal input + shall not be allowed. (Practicality?) + +#. Neither ``locals()`` nor ``globals()`` are necessary nor used during the + transformation, + avoiding leakage of information. + +#. To eliminate complexity as well as ``RuntimeError`` (s) due to recursion + depth, recursive interpolation is not supported. + +#. Restricted characters or expression classes?, such as ``=`` for assignment. + +However, +mistakes or malicious code could be missed inside string literals. +Though that can be said of code in general, +that these expressions are inside strings means they are a bit more likely +to be obscured. + +.. _already handles: https://mail.python.org/pipermail/python-ideas/2015-July/034729.html + + +Mitigation via tools +'''''''''''''''''''' + +The idea is that tools or linters such as pyflakes, pylint, or Pycharm, +could check inside strings for constructs that exceed project policy. +As this is a common task with languages these days, +tools won't have to implement this feature solely for Python, +significantly shortening time to implementation. + +Additionally the Python interpreter could check(?) and warn with appropriate +command-line parameters passed. + + +Backwards Compatibility +----------------------- + +By using existing syntax and avoiding use of current or historical features, +expression-strings (and any associated sub-features), +were designed so as to not interfere with existing code and is not expected +to cause any issues. + + +Postponed Ideas +--------------- + +Internationalization +'''''''''''''''''''' + +Though it was highly desired to integrate internationalization support, +(see PEP 501), +the finer details diverge at almost every point, +making a common solution unlikely: [15]_ + +* Use-cases +* Compile and run-time tasks +* Interpolation Syntax +* Intended audience +* Security policy + +Rather than try to fit a "square peg in a round hole," +this PEP attempts to allow internationalization to be supported in the future +by not preventing it. +In this proposal, +expression-string inputs are saved for inspection and re-rendering at a later +time, +allowing for their use by an external library of any sort. + + +Rejected Ideas +-------------- + +Restricting Syntax to ``str.format()`` Only +''''''''''''''''''''''''''''''''''''''''''' + +This was deemed not enough of a solution to the problem. +It can be seen in the `Implementations in Other Languages`_ section that the +developer community at large tends to agree. + +The common `arguments against`_ arbitrary expresssions were: + +#. YAGNI, "You ain't gonna need it." +#. The change is not congruent with historical Python conservatism. +#. Postpone - can implement in a future version if need is demonstrated. + +.. _arguments against: https://mail.python.org/pipermail/python-ideas/2015-August/034913.html + + +Additional/Custom String-Prefixes +''''''''''''''''''''''''''''''''' + +As seen in the `Implementations in Other Languages`_ section, +many modern languages have extensible string prefixes with a common interface. +This could be a way to generalize and reduce lines of code in common +situations. +Examples are found in ES6 (Javascript), Scala, Nim, and C# +(to a lesser extent). +This was rejected by the BDFL. [14]_ + + +Automated Escaping of Input Variables +''''''''''''''''''''''''''''''''''''' + +While helpful in some cases, +this was thought to create too much uncertainty of when and where string +expressions could be used safely or not. +The concept was also difficult to describe to others. [12]_ + +Always consider expression-string variables to be unescaped, +unless the developer has explicitly escaped them. + + +Environment Access and Command Substitution +''''''''''''''''''''''''''''''''''''''''''' + +For systems programming and shell-script replacements, +it would be useful to handle environment variables and capture output of +commands directly in an expression string. +This was rejected as not important enough, +and looking too much like bash/perl, +which could encourage bad habits. [13]_ + + +Reference Implementation(s) +=========================== + +An expression-string implementation is currently attached to PEP 498, +under the ``f''`` prefix, +and may be available in nightly builds. + +A Python implementation of Ruby interpolation `is also available`_, +which is similar to this proposal. +It uses the codecs module to do its work:: + + ? pip install interpy + + # coding: interpy + location = 'World' + print("Hello #{location}.") + +.. _is also available: https://github.com/syrusakbary/interpy + + +Acknowledgements +================ + +* Eric V. Smith for providing invaluable implementation work and design + opinions, helping to focus this PEP. +* Others on the python-ideas mailing list for rejecting the craziest of ideas, + also helping to achieve focus. + + +References +========== + +.. [1] Briefer String Format + + (https://mail.python.org/pipermail/python-ideas/2015-July/034659.html) + + +.. [2] Briefer String Format + + (https://mail.python.org/pipermail/python-ideas/2015-July/034669.html) + +.. [3] Briefer String Format + + (https://mail.python.org/pipermail/python-ideas/2015-July/034701.html) + +.. [4] Bash Docs + + (http://www.tldp.org/LDP/abs/html/arithexp.html) + +.. [5] Bash Docs + + (http://www.tldp.org/LDP/abs/html/commandsub.html) + +.. [6] Perl Cookbook + + (http://docstore.mik.ua/orelly/perl/cookbook/ch01_11.htm) + +.. [7] Perl Docs + + (http://perl6maven.com/perl6-scalar-array-and-hash-interpolation) + +.. [8] Ruby Docs + + (http://ruby-doc.org/core-2.1.1/doc/syntax/literals_rdoc.html#label-Strings) + +.. [9] Ruby Docs + + (https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Interpolation) + +.. [10] Python Str.Format Syntax + + (https://docs.python.org/3/library/string.html#format-string-syntax) + +.. [11] Python Format-Spec Mini Language + + (https://docs.python.org/3/library/string.html#format-specification-mini-language) + +.. [12] Escaping of Input Variables + + (https://mail.python.org/pipermail/python-ideas/2015-August/035532.html) + +.. [13] Environment Access and Command Substitution + + (https://mail.python.org/pipermail/python-ideas/2015-August/035554.html) + +.. [14] Extensible String Prefixes + + (https://mail.python.org/pipermail/python-ideas/2015-August/035336.html) + + +.. [15] Literal String Formatting + + (https://mail.python.org/pipermail/python-dev/2015-August/141289.html) + + +Copyright +========= + +This document has been placed in the public domain. + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps